IT/Java

[Java] Arrays.sort 와 Collections.sort 정리(comparable, comparator)

jaewon_sss 2023. 2. 25. 21:03
반응형

정렬할 때마다 아 Python 할 걸... 생각이 들게 하는 기능

근데 또 생각하려면 기억 안나서 계속 구글링해야하는 기능

 

정리해두려고합니다.

 

(회사에선 C#쓰면서 Java 못놓는 중,,,)

 

Arrays.sort

 

오름차순

import java.util.Arrays;

public class Sort {
    public static void main(String[] args) {
        String[] str = {"1", "5", "4", "3", "6", "2"};

        for(String s : str) {  // 정렬 전 출력
            System.out.print(s + " ");
        }
        System.out.println();

        Arrays.sort(str);  // 정렬 후 출력
        for(String s : str) {
            System.out.print(s + " ");
        }
    }
}
1 5 4 3 6 2
1 2 3 4 5 6

 

 

내림차순

import java.util.Arrays;
import java.util.Collections;

public class Sort {
    public static void main(String[] args) {
        String[] str = {"1", "5", "4", "3", "6", "2"};

        for(String s : str) {  // 정렬 전 출력
            System.out.print(s + " ");
        }
        System.out.println();

        Arrays.sort(str, Collections.reverseOrder());  // 정렬 후 출력
        for(String s : str) {
            System.out.print(s + " ");
        }
    }
}
1 5 4 3 6 2
6 5 4 3 2 1

 

알고가야할 것 :  배열을 정렬할 땐, Arrays.sort() 사용하기

 

여기까진 쉽네

 

 

Collections.sort   Collections.reverse

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class Sort {
    public static void main(String[] args) {
        String[] str = {"1", "5", "4", "3", "6", "2"};
        List<String> list = Arrays.asList(str);    // 배열 -> List

        System.out.println(list);               // 초기값

        Collections.sort(list);
        System.out.println(list);               // 오름차순

        Collections.reverse(list);
        System.out.println(list);               // 내림차순
    }
}
[1, 5, 4, 3, 6, 2]
[1, 2, 3, 4, 5, 6]
[6, 5, 4, 3, 2, 1]

 

String[] 문자열은 되는 건 알겠는데 왜 int[] 숫자는 안돼...?

 

int[] 말고 Integer[] 로 하면 될거에요.

 

Integer[]는 되긴되네. 그런데 왜 int[] 는 안돼...? 

 

Collections.sort() 메소드는 모든 "객체"를 사용할 수 있게끔 정의됐는데

int 는 primitive type 이라서 사용이 불가능합니다.

 

 

알고가야할 것 :  list를 정렬할 땐, Collections.sort() 사용하기

 

 

 

 

Comparable Interface

 

숫자나 문자는 할만한데 새롭게 정의한 클래스가 있을 때 조금 까다로워져요...

새로운 기준을 잡아줘야 하기 때문입니다.

 

뭔 소리야...?

 

Student.name  = '코린'

Student.score = '90'

 

이 경우, Student 라는 객체를 name? score? 어떤 변수로 비교할지 기준을 잡아줘야한다는 뜻입니다.

 

 

이 때 기준을 잡아주는 것이 Comparable 인터페이스이고

해당 인터페이스를 구현할 클래스에 compareTo 메소드를 오버라이딩하면 정렬이 가능한 클래스가 됩니다.

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

class Student implements Comparable {
    String name;
    int score;

    public Student (String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Object o) {
        Student other = (Student) o;
        return other.score - this.score;
    }

    @Override
    public String toString() {
        return "name = " + name +
                ", score = " + score;
    }
}

public class Sort {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("sim", 80));
        list.add(new Student("kim", 90));
        list.add(new Student("lee", 70));
        list.add(new Student("park", 100));

        System.out.println(list.toString());
        Collections.sort(list);
        System.out.println(list.toString());
    }
}
[name = sim, score = 80, name = kim, score = 90, name = lee, score = 70, name = park, score = 100]
[name = park, score = 100, name = kim, score = 90, name = sim, score = 80, name = lee, score = 70]

 

JAVA는 오름차순이 디폴트입니다.

 

compareTo() 메소드 리턴값은 두 가지 경우의 수로 나뉠거에요.

 

1. return other.score - this.score 

 

      1) other.score > this.score 경우

            other, this 로 되어있는 순서를 this, other로 바꿔야 오름차순이 되겠죠

 

      2) other.score < this.score

            other, this 로 되어있는 순서를 그대로 둬도 오름차순이 되겠죠

 

 

2. return this.score - other.score

 

      1) this.score > other.score 경우

            this, other 로 되어있는 순서를 other, this 로 바꿔야 오름차순이 되겠죠

 

      2) this.score < other.score

            other, this 로 되어있는 순서를 그대로 둬도 오름차순이 되겠죠

 

 

즉, 리턴값이 양수일 경우, 순서를 바꾸고 음수일 경우, 바꾸지 않는다는 결론입니다.

 

 

아... 무슨 말이야...

 

 

말이 굉장히 어렵습니다.... 예를 들어볼게요.

{100, 50} 으로 초기값이 세팅되어있고 이걸 정렬할거에요

 

this.score = '100'

other.score = '50'

 

return this.score - other.score = 50 이 되어 양수입니다.

양수는 순서를 바꾼다고 했죠?

{100, 50} 을 {50, 100} 순으로 순서를 바꾸니까 오름차순이 되었습니다.

 

내림차순으로 정렬하고 싶을 경우,

위에 return this.score - other.score일 경우, 오름차순이었으니

return other.score - this.score 로 변경하면 내림차순이 되겠죠.

 

머리 터진다...

 

그럼 다른 방법이 있는데 Comparator 인터페이스입니다.

 

Comparator

새롭게 정의한 클래스에 Comparable 인터페이스를 implements 했던 것과 다르게

Collections.sort(list, comparator) 의 형태로 정의 되어있어서 Comparator 은 메인 클래스에서 바로 사용할 수 있습니다.

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

class Student {
    String name;
    int score;

    public Student (String name, int score) {
        this.name = name;
        this.score = score;
    }
    @Override
    public String toString() {
        return "name = " + name +
                ", score = " + score;
    }
}

public class Sort {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("sim", 80));
        list.add(new Student("kim", 90));
        list.add(new Student("lee", 70));
        list.add(new Student("park", 100));

        System.out.println(list.toString());

        Collections.sort(list, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                return s1.score - s2.score;
            }
        });
        System.out.println(list.toString());
    }
}
[name = sim, score = 80, name = kim, score = 90, name = lee, score = 70, name = park, score = 100]
[name = lee, score = 70, name = sim, score = 80, name = kim, score = 90, name = park, score = 100]

 

comparable은 기준(this)과 비교대상(other)이 있어 this.compareTo(other) 의 형태로 비교를 했다면,

comparator는 비교 대상 2개를 가지고 비교를 합니다.

 

JAVA는 오름차순이 디폴트이라고 했죠

 

 

compare() 메소드 리턴값도 두 가지 경우의 수로 나뉩니다.

 

1. return o1.score - o2.score 

 

      1) o1.score  > o2.score 경우

            o1, o2 로 되어있는 순서를 o2, o1로 바꿔야 오름차순이 되겠죠

 

      2) o1.score < o2.score

            o1, o2 로 되어있는 순서를 그대로 둬도 오름차순이 되겠죠

 

 

2. return o2.score - o1.score

 

          1) o2.score  > o1.score 경우

            o2, o1 로 되어있는 순서를 o2, o1로 바꿔야 오름차순이 되겠죠

 

      2) o2.score < o1.score

            o2, o1 로 되어있는 순서를 그대로 둬도 오름차순이 되겠죠

 

 

compareTo 나 compare 이나 똑같네 ;

 

 

네 똑같네요.

 

차이점은

 

Comparable 은 클래스에 직접 interface 를 implements 하여 정렬가능한 클래스로 바꾸는 점

Comparator 은 Collections.sort(list, comparator) 의 형태로 정의 되어있어서 메인 클래스에서 바로 사용할 수 있다는 점

이 되겠습니다.

 

정렬 알고리즘 있을 때 꼭 필요한 내용이니까 최소 둘 중 하나는 외우시길 바랍니다.

 

끗 ! 

 

 

반응형