Replies: 3 comments 1 reply
-
알고리즘 문제에서 정렬 커스텀이 필요할때 지긋지긋하게 Comparable 인터페이스의 compareTo 메서드를 오버라이딩 하였는데 제대로 알아보지도 않고 막무가내로 썻던 경험이 있습니다. 특히 intelliJ 에서 특정 클래스가 Comparable을 구현하게 한 후 compareTo 메서드를 재정의 하면 class Num implements Comparable<Num> {
private int num1;
private int num2;
@Override
public int compareTo(Num o) {
if (this.num1 == o.num1) {
return this.num2 - o.num2;
}
return this.num1 - o.num1;
}
} 이러한 equals 메서드를 재정의 하라고 경고를 보여주었는데 (필수X) compareTo 메서드로 수행한 동치성 테스트 결과가 equals의 결과와 같야아 함.
물론 equals를 재정의 했다면 hashCode 또한 재정의 해야 겠죠!! (#23 제가 정리한 자료입니다 ㅎㅎ...)위 코드를 지금까지의 규약을 지키면 아래와 같습니다. class Num implements Comparable<Num> {
private int num1;
private int num2;
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Num num = (Num) o;
return num1 == num.num1 && num2 == num.num2;
}
@Override
public int hashCode() {
return Objects.hash(num1, num2);
}
@Override
public int compareTo(Num o) {
if (this.num1 == o.num1) {
return this.num2 - o.num2;
}
return this.num1 - o.num1;
}
} 이러한 이유가 있었군요! 이번 글을 통해 Comparable, compareTo에 대해 좀 더 알게되었습니다 감사합니다.. |
Beta Was this translation helpful? Give feedback.
-
이 부분을 좀 더 정리해보려고 하는데요,, public class MainClass {
public static void main(String[] args) {
Set<BigDecimal> fooTreeSet = new TreeSet<>();
Set<BigDecimal> fooHashSet = new HashSet<>();
BigDecimal decimal1 = new BigDecimal("123.0");
BigDecimal decimal2 = new BigDecimal("123.000");
fooTreeSet.add(decimal1);
fooTreeSet.add(decimal2);
fooHashSet.add(decimal1);
fooHashSet.add(decimal2);
System.out.printf("BigDecimal equals 결과 = %b", decimal1.equals(decimal2));
System.out.println();
System.out.printf("BigDecimal compareTo 결과 = %b", decimal1.compareTo(decimal2));
System.out.println();
System.out.println("fooTreeSet");
fooTreeSet.forEach(System.out::println);
System.out.println("fooHashSet");
fooHashSet.forEach(System.out::println);
}
} 위 코드의 결과는 이렇네요
TreeSet은 내부적으로 TreeMap으로 구현하고 있고, TreeMap의 put 메서드를 보면 아래와 같습니다. public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
// 여기서 compareTo로 비교를 하고 만약 같은 경우 새로운 value로 덮어씌워버림
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
} https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/math/BigDecimal.html#compareTo(java.math.BigDecimal) BigDecimal의 compareTo와 equals의 설명을 보면, compareTo의 경우 2.0와 2.00 처럼 scale이 달라도 동일한 것으로 간주한다고 되어 있고 equals의 경우 scale이 다르면 다른 것으로 간주한다고 되어 있네요. |
Beta Was this translation helpful? Give feedback.
-
Comparable vs Comparatorhttps://stackoverflow.com/a/4108764 해당 인스턴스에 자연적인 순서가 있는 경우 Comparable을 구현해서 compareTo로 순서 설정. 네이밍만 보면,, Comparable은 이게 비교되어질 수 있다, 순서가 있다, 정렬될 수 있다의 의미인거고,, Comparator는 정렬하기 위한 도구로 보면 될 거 같네요. '이 객체는 정렬될 수 있고, 기본적으로 정렬되어야 하는 기준이 있다'의 경우에만 Comparable을 구현하고,, 그 외 정렬할 때 Comparator를 쓰거나 하면 될 거 같네요. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Comparable
compareTo 메서드의 일반 규약
compareTo 메서드 작성 요령
Comparator
Beta Was this translation helpful? Give feedback.
All reactions