티스토리 뷰

1. Collections

  • Collections는 내부에 static함수가 있기 때문에 객체를 생성하지 않고 바로 메소드를 사용 할 수 있다.
  • Collection 프레임워크 등에서 sort()를 사용하면 컴퓨터가 알아서 정렬을 해 주는데 오늘은 sort()를 이용한 정렬에 대해 알아보고자 한다.
  • 여기서 sort()는 Comparable 구현에 의해 정렬된 것이다.

2. Array.sort()와 Collections.sort()의 차이점은? 아래와 같이 쉽게만 이해하자!

가. Array.sort()

- 배열 정렬의 경우

나. Collections.sort()

- List Collection 정렬의 경우

 

3. Comparator과 Comparable은 무엇이 다른가?

  • Comparator : 기본 정렬기준 외에 다른 기준으로 정렬하고자 할 때 사용
  • Comparable : 기본 정렬기준을 구현하는데 사용
  • 오늘은 Comparator 사용 예제를 다루고 Comparable은 무엇인지 알고만 넘어가고자 한다.

4. Comparator

  • 정렬 가능한 클래스(Comparable 인터페이스를 구현한 클래스)등릐 기본 정렬기준과 다르게 정렬하고 싶을 때
  • 주로 익명 클래스로 사용되고 기본적인 정렬 방법인 오름차순 정렬을 내림차순으로 정렬할 때 많이 사용한다.
  • Collections 내부에 Comparator 가 존재하는데 인터페이스이기 때문에 구현해서 사용해야 한다.
  • Comparator은 정렬 중에서 가장 빠르다는 퀵 정렬을 사용하고 있고 최적화 되어 있기 때문에 직접 정렬 함수를 구현하는 것 보다 훨씬 바르기 때문에 Comparator 인터페이스를 사용하는 것이 좋다.

가. 구현방법

  • Comparator interface를 implements 후 compare() 메서드를 오버라이드한 myComarator class를 작성한다.
  • compare() 메서드 작성법
    • 첫 번째 파라미터로 넘어온 객체 < 두 번째 파라미터로 넘어온 객체 : 음수 리턴
    • 첫 번째 파라미터로 넘어온 객체 == 두 번째 파라미터로 넘어온 객체 : 0 리턴
    • 첫 번째 파라미터로 넘어온 객체 > 두 번째 파라미터로 넘어온 객체 : 양수 리턴
  • 음수 또는 0이면 객체의 자리가 그대로 유지되며, 양수인 경우에는 두 객체의 자리가 변경된다.

나. 사용방법

  • Arrays.sort(array, myComparator)
  • Collections.sort(list, myComparator)
  • Arrays.sort(), Collections.sort() 메서드는 두 번째 인자로 Comparator interface를 받을 수 있다.

5. Comparable

  • 정렬 수행 시 기본적으로 적용되는 정렬 기준이 되는 메서드를 정의하는 인터페이스
  • Java에서 제공되는 정렬이 가능한 클래스들은 모두 Comparable 인터페이스를 구현하고 있으며, 정렬 시에 이에 맞게 정렬이 수행된다.

가. 구현방법

  • 정렬할 객체에 Comparable inteface를 implements 한 후, compareTo() 메서드를 오버라이드하여 구현한다.
  • compateTo() 메서드 작성법
    • 현재 객체 < 파라미터로 넘어온 객체 : 음수 리턴
    • 현재 객체 == 파라미터로 넘어온 객체 : 0리턴
    • 현재 객체 > 파라미터로 넘어온 객체 : 양수 리턴
    • 음수 또는 0이면 객체의 자리가 그대로 유지되며, 양수인 경우에는 두 객체의 자리가 바뀐다.

나. 사용 방법

  • Arrays.sort(array)
  • Collections.sort(list)

6. 정렬 예제(LinkedList와 Collections, Comparator 활용)

가. LinkedList와 객체(인수 2개)를 이용한 정렬

  • 아래에 있는 클래스를 이용해 5개의 예제 실시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A {
    // 필드
    int n;
    String s;
    // 생성자
    public A(int n, String s) {
        this.n = n;
        this.s = s;
    }
    // 메서드
    void output() {
        System.out.println("num : " + n + ", s : " + s);
    }
}
cs

 

  • Main 함수
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Main
public static void main(String[] args) {
    LinkedList<A> list = new LinkedList<A>();
        
    list.add(new A((int)(Math.random()*100) % 100"호랑이"));
    list.add(new A((int)(Math.random()*100) % 100"코끼리"));
    list.add(new A((int)(Math.random()*100) % 100"독수리"));
    list.add(new A((int)(Math.random()*100) % 100"맘모스"));
    list.add(new A((int)(Math.random()*100) % 100"코뿔소"));
        
    System.out.println("정렬 전");
    for (A item : list) {
        item.output();
    }
    
    System.out.println("----------------------------------");
}
cs
  • Ex01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        // Ex01
        // 가장 기본적인 
 
        Collections.sort(list, new Comparator<A>() {
            // compare 함수를 사용하여 정렬을 어떻게 할 것인지 정의한다.
            @Override
            public int compare(A o1, A o2) {
                // 순차 정렬을 해주는 코드(역방향은 부등호를 변경하거나 return 값을 바꿔주면 됨)
                // if-else 동등의 개념을 포함 , -1이 있기 때문에 +1로 적어서 동등하게 맞춰준다.
                if(o1.n > o2.n) // if(o1.n < o2.n) : 역순
                    return +1;    // 양수의 대명사를 +1이라고 본다.
                else
                    return -1;
 
            }
        });
cs
  • Ex02
1
2
3
4
5
6
7
8
9
10
        // Ex02
        // Ex01의 compare 함수 안 코드를 삼항 연산자로 변경
        Collections.sort(list, new Comparator<A>() {
            // compare 함수를 사용하여 정렬을 어떻게 할 것인지 정의한다.
            @Override
            public int compare(A o1, A o2) {
                return (o1.n > o2.n) ? +1 : -1;
            }
            
        });
cs
  • Ex03
1
2
3
4
5
6
7
8
9
        // Ex03
        // o1.n은 양수를, o2.n은 음수를 반환받는 것이기 때문에 Ex01 처럼 if-else를 사용하지 않아도 된다.
 
        Collections.sort(list, new Comparator<A>() {
            @Override
            public int compare(A o1, A o2) {
                return o1.n - o2.n;
            }
        });
cs
  • Ex04
1
2
3
4
5
6
7
8
        // Ex04
        // Ex03을 람다식으로 변환
        // new를 없애고 함수 이름을 없앤 다고 생각하고 없애면 된다. 인수의 타입은 선언하지 않아도 된다
        // 람다식으로 변환하는 방법만 알아두면 앞으로도 쉽게 람다식으로 변환 할 수 있다.
 
        Collections.sort(list, (o1, o2) -> {
                return o1.n - o2.n;
        });
cs
  • Ex05
1
2
3
4
5
        // Ex05
        // Ex04를 다른형태의 람다식으로 변환
        // 람다식 안에 코드가 한 줄 일 경우 스코프를 생략 할 수 있는데 return도 같이 제거해 주어야 한다.
 
        Collections.sort(list, (o1, o2) -> o1.n - o2.n );
cs

Ex01 - Ex05 실행결과

  • 위 Ex01 - Ex05 까지 모두 같은 실행결과를 가지는 예제이다.
  • 동일한 결과 값을 출력하는 5가지의 예시지만 Ex01 기본적인 사용법부터 Ex05 까지 코드를 줄이면서 변형한 예제 까지 알아두면 좋다. (람다식 적용)
  • 만약에 A클래스의 필드 n이 float형이라면 반드시 Ex02 예제 처럼 코드를 작성해야 하며 int인 경우에는 모든 예제를 사용 해서 코드를 작성 할 수 있지만 Ex05 번이 가장 많이 사용 되는 예제이다.

나. LinkedList와 객체(인수 3개)를 이용한 정렬

  • '가'에서 나온 예제와 유사하지만 클래스에 필드 변수를 하나 더 선언해 인수 3개를 활용한 예시이다.
  • '나'는 필드 n1과 n2의 곱을 가지고 정렬하는 예제로 '가' 예제와 큰 차이가 없다.
  • 전체 소스코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package D_0723;
 
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
 
// LinkedList 정렬 기법2
// n1과 n2를 곱한 값의 정렬
 
class A1 {
    // 필드
    int n1, n2;
    String s;
    // 생성자
    public A1(int n1, int n2, String s) {
        this.n1 = n1;
        this.n2 = n2;
        this.s = s;
    }
    // 메서드
    void output() {
        System.out.println("n1 : " + n1 + ", n2 : " + n2 + ", s : " + s);
    }
}
 
public class Ex02 {
    public static void main(String[] args) {
        LinkedList<A1> listA = new LinkedList<A1>();
        
        listA.add(new A1(1213"호랑이"));
        listA.add(new A1(1011"코끼리"));
        listA.add(new A1(1514"독수리"));
        listA.add(new A1(810"맘모스"));
        listA.add(new A1(511"코뿔소"));
 
        System.out.println("정렬 전");
        
        for (A1
                item : listA) {
            item.output();
        }
        
        System.out.println("----------------------------------");
        
        // n1과 n2를 곱한 값의 정렬
        
        Collections.sort(listA, new Comparator<A1>() {
            @Override
            public int compare(A1 o1, A1 o2) {
 
                int r1 = o1.n1 * o1.n2;
                int r2 = o2.n1 * o2.n2;
                if(r1 > r2) 
                    return +1;    
                else
                    return -1;
    
            }
        });
        System.out.println("정렬 후");
        
        for (A1
                item : listA) {
            item.output();
        }
    }
}
 
cs
  • 실행결과

실행 결과('나')

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함