작성자 없음
작성자 정보가 삭제된 글입니다.
작성
·
284
0
안녕하세요 현재 자바의 정석 : 기초편으로 컬렉션 프레임워크를 학습하고 있습니다.
학습 중 comparable과 comparaor가 잘 이해가 되지 않아서 질문을 드립니다.
public static void main(String[] args) {
String[] strArr = {"cat" , "Dog" , "lion" , "tiger"};
Integer[] intArr = {1,5,3,4,7,2,6};
Arrays.sort(intArr);
System.out.println(Arrays.toString(intArr));
Arrays.sort(intArr, new Descending());
System.out.println(Arrays.toString(intArr));
Arrays.sort(strArr);
System.out.println("Arrays.sort(strArr) = " + Arrays.toString(strArr));
//정렬한 후 [Dog, cat, lion, tiger]
Arrays.sort(strArr , String.CASE_INSENSITIVE_ORDER);
System.out.println("strArr = " + Arrays.toString(strArr));
//대소문자 구별 X = > [cat, Dog, lion, tiger]
System.out.println(Arrays.toString(strArr));
Arrays.sort(strArr , new Descending());
System.out.println("strArr = " + Arrays.toString(strArr));
}
class Descending implements Comparator{
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Comparable && o2 instanceof Comparable ){
Comparable c1 = (Comparable)o1;
Comparable c2 = (Comparable)o2;
return c1.compareTo(c2)*-1;
}
return -1;
}
현재 제가 이해한 부분은 다음과 같습니다.
정렬은 두 대상을 비교하고 자리바꿈을 하는 것
정렬을 위해서는 정렬에 대한 기준이 필요하다
하지만 Array.sort(strArr);
정렬에 대한 대상은 존재하지만 정렬에 대한 기준이 없다.
String , Integer 등과 같은 클래스는 comparable이 구현되어 있다. 따라서 sort메서드를 실행할 때 정렬에 대한 기준이 x => 기본적으로 오름차순으로 정렬한다.
strArr은 오름차순으로 정렬된 값이다.
Arraty.sort(strArr , String.CASE_INSENSTIVE_ORDER);
strArr([Dog, cat, lion, tiger])을 대소문자 상관없이 정렬
따라서 strArr = {cat,Dog, lion, tiger} 순으로 정렬된다.
Array.sort(strArr , new Descending());
strArr를 사용자 정의 정렬 기준으로 정렬한다.
제가 이해가 되지 않는 부분은 다음과 같습니다.
Descending 클래스를 디버깅을 해보았으며 o1에는 Dog가 들어오고 o2는 cat이 들어가는데 왜 그런지 모르겠습니다.
strArr = {cat,Dog, lion, tiger}인데 왜 Dog가 o1에 들어가고 cat이 o2에 들어가고 또한 o2가 더 크니 음수를 리턴하는데 각 각 char의 총합의 차를 반환하는 것인가요?
디버깅 이후 스텝 오버를 해봤습니다. o1에는 lion이 들어가고 o2에는 Dog가 들어가던데 왜 그러한지 잘 모르겠습니다.
그리고 int[]도 확인해보았는데 오름차순으로 정렬되었으니 [1,2,3,4,5,6,7] 이며 Descending에 디버깅을 해보았는데 o1에는 2가 o2에는1이 스텝오버를 하니 o1에는 3이 o2에는 2가 대입되더라구요 이것 또한 잘 이해가 되지 않아서 질문을 드립니다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. 옙버디님, Comparable과 Comparator에 대해 질문 주셨군요. 일단 질문 주신 내용을 바탕으로 Comparable과 Comparator의 차이와 사용 방법에 대해 설명드리겠습니다.
Comparable 인터페이스는 객체 자체에 비교 메소드인 compareTo를 구현하도록 하여, 각 객체가 자신과 다른 객체를 비교하는 방법을 내부에 포함하게 합니다. 이를 자연 순서(natural ordering)라고 하며, 정렬할 때 별도의 비교 방법을 지정하지 않으면 객체가 구현한 compareTo 메소드에 따라 정렬됩니다.
Comparator 인터페이스는 별도의 compare 메소드를 통해 두 객체를 비교하는 방법을 정의합니다. 이를 자연 순서에서 벗어나 원하는 대로 정렬 기준을 설정할 때 사용합니다.
Arrays.sort(strArr);
이 부분에서 strArr 배열에 대해 정렬을 수행할 때 String 클래스가 이미 Comparable 인터페이스를 구현하고 있으므로, String 클래스의 compareTo 메소드에 정의된 ‘자연 순서’에 따라 문자열이 오름차순으로 정렬됩니다.
Arrays.sort(strArr, String.CASE_INSENSITIVE_ORDER);
이 부분에서는 Comparator를 파라미터로 전달하여 대소문자를 무시한 채 문자열을 비교하는 방식으로 정렬되도록 하고 있습니다.
Arrays.sort(strArr, new Descending());
여기서는 사용자가 정의한 Descending 클래스(Comparator를 구현)를 이용하여 정렬 기준을 지정합니다. Descending 클래스의 compare 메소드에서는 두 객체 o1과 o2를 비교하여 기존 compareTo 메소드의 결과에 -1을 곱함으로써 역순으로 정렬하도록 합니다.
질문하신 Descending 클래스를 통해 정렬을 할 때 Dog가 o1에 들어가고 cat이 o2에 들어가는 이유는 Arrays.sort 메소드가 내부적으로 객체들을 비교하며 정렬을 수행할 때 Comparator의 compare 메소드를 호출하기 때문입니다. 이 과정에서 어떤 객체가 첫 번째 매개변수(o1)로 들어가고 어떤 객체가 두 번째 매개변수(o2)로 들어갈지 결정됩니다.
각 문자의 총합을 반환하는 것이 아니라, compareTo 메소드는 두 문자열을 순차적으로 비교하여 첫 번째로 다른 점이 나오는 문자가 있을 때 그 차이를 기반으로 결과를 반환합니다. 대소문자 구분 없이 정렬될 때는 완전한 문자열 비교가 아니라 대소문자 구분 없이 비교하는 Comparator가 사용됩니다.
int[] 배열 같은 경우 Primitive 타입은 Comparable 인터페이스가 아닌 자바 자체적인 정렬 메커니즘을 사용하여 오름차순으로 정렬됩니다.
중요한 점은 Comparator 구현체를 사용하는 정렬에서는 compare 메소드가 Comparator 구현체의 비교 로직에 따라 두 객체의 비교 순서를 결정하고, 이를 바탕으로 전체 배열이나 리스트가 정렬된다는 것입니다. 따라서 Descending 클래스에서 구현한 비교 로직에 따라 strArr나 intArr의 요소들이 역순으로 정렬되었을 것입니다.
질문하신 내용에 대한 답변이 충분히 이해가 되시길 바랍니다. 추가적인 질문이나 궁금한 점이 있다면 언제든 질문해주세요!
이해가 안가는 부분이 있습니다.
왜 Dog가 o1에 들어가고 cat이 o2에 들어가나요?
해당 구문을 실행하기 전까지는 strArr은 {"cat" , "Dog" ,"lion","tiger"}인데 해당 로직을 만나면 strArr의 값이 순서대로 o1에는 cat이 o2에는 Dog가 들어가야하는게 아닌가 라는 생각이 듭니다.