CodeGym/Java Blog/무작위의/자바의 Comparator 클래스
John Squirrels
레벨 41
San Francisco

자바의 Comparator 클래스

무작위의 그룹에 게시되었습니다
회원
안녕! 오늘 우리는 객체 비교에 대해 이야기할 것입니다. Java의 비교기 클래스 - 1 음... 하지만 우리가 이미 이 주제에 대해 한 번 이상 이야기하지 않았나요? :/ ==연산자가 작동하는 방식과 및 equals()메서드 를 알고 있습니다 hashCode(). 비교는 조금 다릅니다. 이전에는 "객체가 같은지 확인"을 의미했을 가능성이 큽니다. 그러나 객체를 서로 비교하는 이유는 완전히 다를 수 있습니다! 이들 중 가장 분명한 것은 정렬입니다. 숫자나 문자열을 정렬하라는 지시를 받았다면 ArrayList<>아무 문제 없이 처리할 수 있을 것입니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       String name1 = "Masha";
       String name2 = "Sasha";
       String name3 = "Dasha";

       List<String> names = new ArrayList<>();
       names.add(name1);
       names.add(name2);
       names.add(name3);

       Collections.sort(names);
       System.out.println(names);
   }
}
콘솔 출력:
[Dasha, Masha, Sasha]
Collections수업과 그 방법을 기억했다면 sort()잘한 것입니다! 나는 당신이 또한 숫자에 문제가 없을 것이라고 생각합니다. 다음은 더 어려운 작업입니다.
public class Car {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   // ...getters, setters, toString()

}

import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);
   }
}
작업은 실제로 간단합니다. Car클래스와 3개의 Car 객체가 있습니다 . 목록에 있는 자동차를 친절하게 정렬해 주시겠습니까? "어떻게 분류해야 합니까?"라고 물을 것입니다. 이름으로? 제조년도 기준? 최대 속도로? 훌륭한 질문입니다. 현재 우리는 Car개체를 정렬하는 방법을 모릅니다. 그리고 아주 자연스럽게 자바도 그것을 모릅니다! Car메서드 에 개체 목록을 전달하려고 하면 Collections.sort()오류가 발생합니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(20012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       // Compilation error!
       Collections.sort(cars);
   }
}
실제로 언어가 작성한 클래스의 객체를 정렬하는 방법을 어떻게 알 수 있습니까? 이것은 프로그램이 수행해야 하는 작업에 따라 다릅니다. 우리는 어떻게든 Java에게 이러한 객체를 비교하도록 가르쳐야 합니다. 그리고 우리가 원하는 방식으로 비교합니다. Java에는 이를 위한 특별한 메커니즘인 인터페이스가 있습니다 Comparable. 어떻게든 객체를 비교하고 정렬하기 위해 Car클래스는 다음과 같은 단일 메서드로 구성된 인터페이스를 구현해야 합니다 compareTo().
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return 0;
   }

   // ...getters, setters, toString()

}
참고단지 . Comparable<Car>_ Comparable이것은 매개변수화된 인터페이스입니다. 즉, 특정 관련 클래스를 지정해야 합니다. <Car>원칙적으로 인터페이스에서 제거할 수 있지만 비교는 Object기본적으로 개체를 기반으로 합니다. 메소드 대신에 compareTo(Car o)우리 클래스는 다음을 가질 것입니다:
@Override
   public int compareTo(Object o) {
       return 0;
   }
물론 작업하기가 훨씬 쉽습니다 Car. 메서드 내에서 compareTo()자동차를 비교하기 위한 논리를 구현합니다. 제조 연도별로 정렬해야 한다고 가정합니다. 메서드 가 가 아니라 compareTo()를 반환한다는 사실을 눈치채셨을 것입니다 . 이것이 당신을 놀라게 하지 마십시오. 두 개체를 비교할 때 세 가지 가능성이 있습니다. intboolean
  • а < b
  • a > b
  • a == b.
booleantrue와 false의 2개 값만 있으며 개체를 비교하는 데 적합하지 않습니다. 를 사용하면 int모든 것이 훨씬 간단해집니다. 반환 값이 > 0이면 a > b. 의 결과 compareTo< 0이면 a < b. 그리고 결과가 이면 == 0두 객체는 ​​같습니다: a == b. 제조 연도별로 자동차를 분류하도록 수업을 가르치는 것은 쉽습니다.
@Override
public int compareTo(Car o) {
   return this.getManufactureYear() - o.getManufactureYear();
}
하지만 여기서 무슨 일이 일어나고 있습니까? 우리는 하나의 Car 객체( this)를 가져와 이 자동차의 제조 연도를 가져오고 다른 자동차(객체가 비교되는 자동차)의 제조 연도를 뺍니다. 첫 번째 자동차의 제조 연도가 더 크면 이 메서드는 를 반환합니다 int > 0. this car >이것은 자동차 를 의미합니다 o. 반대로 두 번째 자동차( )의 제조 연도가 о더 크면 이 메서드는 음수를 반환합니다 o > this. 마지막으로, 동일하면 메서드는 를 반환합니다 0. 이 간단한 메커니즘은 개체 컬렉션을 정렬하는 데 이미 충분합니다 Car! 다른 작업을 수행할 필요가 없습니다. 확인 해봐:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       // There was previously an error here
       Collections.sort(cars);
       System.out.println(cars);
   }
}
콘솔 출력:
[Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350},
Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}]
차는 우리가 원하는대로 정렬됩니다! :) Java의 비교기 클래스 - 2언제 사용해야 합니까 Comparable? 에서 구현된 비교 방법을 Comparable자연 순서라고 합니다. compareTo()메서드에서 이 클래스의 개체를 비교하는 가장 일반적이거나 자연스러운 방법을 정의하기 때문입니다 . Java에는 이미 자연스러운 순서가 있습니다. 예를 들어 Java는 문자열이 가장 자주 알파벳순으로 정렬되고 숫자는 숫자 값이 증가한다는 것을 알고 있습니다. 따라서 숫자나 문자열 목록에서 메서드를 호출하면 sort()정렬됩니다. 프로그램이 일반적으로 제조 연도별로 자동차를 비교하고 정렬하는 경우 인터페이스 Comparable<Car>compareTo()방법. 그러나 이것이 우리에게 충분하지 않다면 어떨까요? 우리 프로그램이 그렇게 간단하지 않다고 상상해 봅시다. 대부분의 경우 자동차의 자연 분류(제조 연도별로 수행하도록 설정)가 적합합니다. 그러나 때때로 우리 고객은 빠른 운전의 애호가입니다. 그들이 열람할 수 있도록 자동차 카탈로그를 준비하는 경우 자동차는 최대 속도별로 정렬되어야 합니다. Java의 비교기 클래스 - 3예를 들어 시간의 15%를 이와 같이 정렬해야 한다고 가정합니다. Car클래스의 자연스러운 정렬을 제조 연도가 아닌 속도로 설정하기에는 분명히 이것만으로는 충분하지 않습니다 . 하지만 고객의 15%를 무시할 수는 없습니다. 그래서 우리는 무엇을 해야 합니까? 여기에서 또 다른 인터페이스가 도움이 됩니다 Comparator. 와 마찬가지로 Comparable매개변수화된 인터페이스입니다. 차이점이 뭐야? Comparable객체를 "비교 가능"하게 만들고 가장 자연스러운 정렬 순서, 즉 대부분의 경우에 사용되는 정렬 순서를 정의합니다. Comparator별도의 "비교" 인터페이스입니다. 일종의 특수 정렬 순서를 구현해야 하는 경우 클래스로 이동하여 Car의 논리를 변경할 필요가 없습니다 compareTo(). 대신 Comparator를 구현하는 별도의 클래스를 만들고 필요한 정렬을 수행하는 방법을 가르칠 수 있습니다!
import java.util.Comparator;

public class MaxSpeedCarComparator implements Comparator<Car> {

   @Override
   public int compare(Car o1, Car o2) {
       return o1.getMaxSpeed() - o2.getMaxSpeed();
   }
}
보시다시피 우리는 Comparator매우 간단합니다. 하나의 인터페이스 메서드만 구현하면 됩니다 compare(). 두 개체를 입력으로 사용 Car하고 일반적인 방식(빼기)으로 최대 속도를 비교합니다. 마찬가지로 compareTo()an 을 반환하며 int비교 원리는 동일합니다. 이것을 어떻게 사용합니까? 모두 간단합니다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Car> cars = new ArrayList<>();

       Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
       Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
       Car bugatti = new Car(2010, "Bugatti Veyron", 350);

       cars.add(ferrari);
       cars.add(bugatti);
       cars.add(lambo);

       Comparator speedComparator = new MaxSpeedCarComparator();
       Collections.sort(cars, speedComparator);

       System.out.println(cars);
   }
}
콘솔 출력:
[Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290},
Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}]
비교기 객체를 만들고 Collections.sort()정렬할 목록과 함께 메서드에 전달하기만 하면 됩니다. 메소드가 비교자를 받으면 클래스의 메소드 sort()에 정의된 자연 정렬을 사용하지 않습니다 . 대신 전달된 비교기에 의해 정의된 정렬 알고리즘을 적용합니다. 이렇게 하면 어떤 이점이 있습니까? 첫째, 기존 코드와의 호환성. 우리는 대부분의 시간을 사용할 기존 정렬을 유지하면서 새로운 특수 정렬 방법을 만들었습니다. 우리는 수업을 전혀 건드리지 않았습니다 . 그것은 이었으므로 다음과 같이 남아 있습니다. CarcompareTo()CarComparable
public class Car implements Comparable<Car> {

   private int manufactureYear;
   private String model;
   private int maxSpeed;

   public Car(int manufactureYear, String model, int maxSpeed) {
       this.manufactureYear = manufactureYear;
       this.model = model;
       this.maxSpeed = maxSpeed;
   }

   @Override
   public int compareTo(Car o) {
       return this.getManufactureYear() - o.getManufactureYear();
   }

   // ...getters, setters, toString()

}
둘째, 유연성. 원하는 만큼 정렬 알고리즘을 추가할 수 있습니다. 예를 들어 색상, 속도, 무게 또는 배트맨 영화에서 자동차가 사용된 횟수를 기준으로 자동차를 정렬할 수 있습니다. 우리가 해야 할 일은 추가로 Comparator. 그게 다야! 오늘 여러분은 직장에서 실제 프로젝트에서 자주 사용하게 될 두 가지 매우 중요한 메커니즘을 공부했습니다. 그러나 아시다시피 실천 없는 이론은 아무것도 아닙니다. 이제 지식을 통합하고 몇 가지 작업을 완료할 때입니다!
코멘트
  • 인기
  • 신규
  • 이전
코멘트를 남기려면 로그인 해야 합니다
이 페이지에는 아직 코멘트가 없습니다