반응형
- Object.equals에 더해서 순서까지 비교할 수 있으며 Generic을 지원한다.
- this가 compareTo에 전달된 객체보다 작으면 음수, 같으면 0, 크다면 양수를 리턴한다.
- 반사성, 대칭성, 추이성을 만족해야 한다.
- 반드시 따라야 하는 것은 아니지만 x.compareTo(y)==0이라면 x.equals(y)가 true여야 한다.
구현 방법
자연적인 순서를 제공할 클래스에 implements Comparatable <T>을 선언한다.
compareTo 메서드를 오버라이드 한다.
public class CompareNumber implements Comparable<CompareNumber>{
@Override
public int compareTo(CompareNumber o) {
return 0;
}
}
compareTo 메서드 안에서 기본 타입은 박싱 된 기본 타입의 compare을 사용해 비교한다.
핵심 필드가 여러 개라면 비교 순서가 중요하다. 순서를 결정하는 데 있어서 가장 중요한 필드를 비교하고 그 값이 0이라면 (같다면) 다음 필드를 비교한다.
public class CompareNumber implements Comparable<CompareNumber>{
private int order;
private int slotNo;
@Override
public int compareTo(CompareNumber o) {
int result = Integer.compare(order, o.order);
if (result == 0) {
result = Integer.compare(slotNo, o.slotNo);
}
return result;
}
}
기존 클래스를 확장하고 필드를 추가하는 경우 Composition을 활용할 것
public class CompareNumber implements Comparable<CompareNumber>{
private int order;
private int slotNo;
@Override
public int compareTo(CompareNumber o) {
int result = Integer.compare(order, o.order);
if (result == 0) {
result = Integer.compare(slotNo, o.slotNo);
}
return result;
}
}
public class ExtendsNumber extends CompareNumber{
private int x, y;
}
부모를 비교한 후 자식을 비교한다.
public class ExtendsNumber extends CompareNumber{
private int x, y;
public ExtendsNumber(int x, int y) {
this.x = x;
this.y = y;
}
public static void main(String[] args) {
ExtendsNumber extendsNumber1 = new ExtendsNumber(3, 2);
ExtendsNumber extendsNumber2 = new ExtendsNumber(5, 2);
TreeSet<ExtendsNumber> en = new TreeSet<>(new Comparator<ExtendsNumber>() {
@Override
public int compare(ExtendsNumber o1, ExtendsNumber o2) {
int compare = Integer.compare(o1.order(), o2.order());
if (compare == 0) {
compare = Integer.compare(o1.slotNo(), o2.slotNo());
}
if (compare == 0) {
compare = Integer.compare(o1.x, o2.x);
}
return compare;
}
});
en.add(extendsNumber1);
en.add(extendsNumber2);
}
}
상속을 사용한 이후 필드를 추가하면 equals 규약이 깨진다. 그래서 그냥 상속 말고 Composition을 사용하자.
public class ExtendsNumber implements Comparable<ExtendsNumber>{
private int x, y;
private CompareNumber compareNumber;
public ExtendsNumber(int x, int y, CompareNumber compareNumber) {
this.x = x;
this.y = y;
this.compareNumber = compareNumber;
}
public CompareNumber compareNumber() {
return compareNumber;
}
@Override
public int compareTo(ExtendsNumber o) {
int result = this.compareNumber.compareTo(o.compareNumber);
if (result == 0) {
result = Integer.compare(this.x, o.x);
}
return result;
}
}
하지만 자바 8 버전부터는 함수형 인터페이스를 이용하여 쉽게 쉽게 짧게 가능하다.
COMPARATOR의 스태틱 메서드를 활용해서 Comparator 인스턴스를 쉽게 만들 수 있다.
이전에는 implements Comparable <T>을 사용했던 것과 차이점이 존재한다.
@FunctionalInterface
public interface Comparator<T> {
public static <T, U> Comparator<T> comparing(
Function<? super T, ? extends U> keyExtractor,
Comparator<? super U> keyComparator)
{
Objects.requireNonNull(keyExtractor);
Objects.requireNonNull(keyComparator);
return (Comparator<T> & Serializable)
(c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
keyExtractor.apply(c2));
}
}
Function을 첫 번째 인자로 주고 값을 비교할 Comparator을 준다. 만약 두 번째 없다면 꺼내온 값의 naturalOrder가 적용된다.
public static void main(String[] args) {
Comparator.comparing((CompareNumber c) -> c.order)
.thenComparing(CompareNumber::getOrder)
.thenComparing(CompareNumber::getSlotNo);
}
성능에 대해 고려할 때 네트워크보다 이쪽에서 병목현상이 발생한다면 직접 구현하는 걸로 바꿔서 사용해보자.
반응형
'JAVA > [JAVA] 바구니' 카테고리의 다른 글
Increasing Code Cache (0) | 2023.02.20 |
---|---|
equals 정의 (0) | 2022.11.10 |
finalizer와 cleaner 사용을 피하라 (0) | 2022.11.07 |
Exception (0) | 2022.09.25 |
SSL/TLS 서버 통신 (JSSE, TrustManager) (1) | 2021.11.06 |
댓글