비교 라이브러리가 여러 종류라 평소에 헷갈렸던 개념들을 정리하고 가려고 한다.
비교하는 Object에는 String Class
와 Wrapper Class
도 포함된다.
java.lang.Comparable< T>
공식문서에 의하면 클래스의 자연 순서, 즉 기본 정렬 기준이 되는 메서드를 정의하는 인터페이스이다.
(This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.)
Comparable 인터페이스를 구현한 뒤에, 내부에 있는 compareTo 메서드를 원하는 정렬 기준대로 구현하여 사용한다.
class Student implements Comparable<Student> {
int grade;
// compareTo 메서드 오버라이드
@Override
public int compareTo(Student anotherStudent) {
return Integer.compare(grade, anotherStudent.grade);
}
}
public static void main(String[] args){
Integer x = 3;
Integer y = 4;
Double z = 1.0;
System.out.println( x.compareTo(y) ); // return -1
System.out.println( x.compareTo(3) ); // return 0
System.out.println( x.compareTo(2) ); // return 1
System.out.println( z.compareTo(2.7) ); // return -1
}
public static void main(String[] args){
String str = "abcd";
// 1) 비교대상에 문자열이 포함되어있을 경우
System.out.println( str.compareTo("abcd") ); // return 0 (같은 경우는 숫자나 문자나 0을 리턴)
System.out.println( str.compareTo("ab") ); // return 2
System.out.println( str.compareTo("a") ); // return 3
System.out.println( str.compareTo("c") ); // return -2
System.out.println( "".compareTo(str) ); // return -4
// 2) 비교대상과 전혀 다른 문자열인 경우
System.out.println( str.compareTo("zefd") ); // return -25
System.out.println( str.compareTo("zEFd") ); // return -25
System.out.println( str.compareTo("ABCD") ); // return 32
}
java.util.Comparator< T>
공식문서 에 의하면 객체 Collection에 대해 더 정확한 정렬 기준을 정하는 인터페이스이다.
(to allow precise control over the sort order.)
즉,
Comparator
는 클래스의 기본 정렬 기준을 정의한다면,Comparable
은 기본 정렬 기준과 다른 방식으로 정렬하고 싶은 경우 전체 정렬 기준을 정의하는 인터페이스이다.
주로 Collections의 정렬 관련 메서드에 Comparator를 익명 객체로 넣어 정렬 기준을 변경하는 데 사용한다.
Arrays.sort(room, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compare(s2);
}
}
compareTo
는 자기 자신과 매개변수를 비교하는 Comparable 메서드로, 클래스의 기본 정렬 기준을 정의하기 때문에 반드시 구현해야 한다.compare
는 두 매개변수 객체를 비교하는 Comparator메서드로, 정렬 기준 재정의 시 오버라이드하여 사용하는 메서드이다.Byte, Double, Integer, Float, Long, Short의 숫자형 비교는 Comparable의 compareTo 메서드로 비교가능하다.
그렇다면 Wrapper Class가 아닌 Primitive Type의 정수형은 어떻게 비교해야 할까?
static <T> Comparator<T> comparingInt(ToIntFunction <T> keyExtractor)
public static void main(String[] args)
{
// create some user objects
User u1 = new User("Aaman", 25);
User u2 = new User("Joyita", 22);
User u3 = new User("Suvam", 28);
User u4 = new User("mahafuj", 25);
// before sort
List<User> list
= Arrays.asList(u2, u1, u4, u3);
System.out.println("Before Sort:");
list.forEach(User
-> System.out.println("User age "
+ User.getAge()));
// comparingInt로 User의 age 비교
Collections.sort(list,
Comparator.comparingInt(
User::getAge));
System.out.println("\nAfterSort:");
list.forEach(User
-> System.out.println("User age "
+ User.getAge()));
}
}
class User implements Comparable<User> {
public String name;
public int age;
public User(String name, int age)
{
this.name = name;
this.age = age;
}
public int compareTo(User u1)
{
return name.compareTo(u1.name);
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
public String toString()
{
return "User [name=" + name
+ ", age=" + age + "]";
}
}
// int[][] arr
Arrays.sort(arr, Comparator.comparingInt(o1 -> o1[0]));
/**
* Compares two {@code int} values numerically.
* The value returned is identical to what would be returned by:
* <pre>
* Integer.valueOf(x).compareTo(Integer.valueOf(y))
* </pre>
*
* @param x the first {@code int} to compare
* @param y the second {@code int} to compare
* @return the value {@code 0} if {@code x == y};
* a value less than {@code 0} if {@code x < y}; and
* a value greater than {@code 0} if {@code x > y}
* @since 1.7
*/
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
두 정수형 타입의 값들을 비교하여 -1, 0, 1을 반환하는 메서드다.
public static void main(String... args) {
System.out.println(Integer.compare(1, 2)); // return -1
System.out.println(Integer.compare(2, 2)); // return 0
System.out.println(Integer.compare(3, 2)); // return 1
}
// int[][] arr
Arrays.sort(dungeons, (o1,o2) -> {
// 첫 번째 요소 같을 시 두 번째 요소 비교
if(o1[0] == o2[0]){
// 두 번째 요소 비교하여 오름차순 정렬
return Integer.compare(o1[1],o2[1]);
// 첫 번째 요소 같지 않을 시
} else {
// 첫 번째 요소 비교하여 내림차순 정렬
return Integer.compare(o2[0], o1[0]);
}
});