DEV/Java

[java] Comparable 활용 Collections.sort() 정렬 방식 정의

Bi3a 2023. 10. 12. 20:13

목차
반응형

Collections.sort() 정렬 방식 정의
java 기초 깨부시기

 


 

Comparable <T> 인터페이스

`Comparable` 인터페이스는 `Comparator` 와 함께 정렬 규칙을 재정의해 객체 정렬을 가능하게 합니다.
`Arrays.sort()`과 같이 java에서 기본으로 제공하는 static 메서드로는 객체를 정렬할 수 없습니다.

 

Comparable vs Comparator

  • `Comparable` : 결과값인 정수값에 따라 객체를 대상으로 기본 정렬 기준을 정의하는 데 사용(오름차순, 내림차순 등)
  • `Comparator` : 기본 정렬 값 제외한 다른 기준을 정의할 때 사용

 

Comparable을 활용한 Collections.sort 메소드 호출의 이해

 

Collections.sort java official api
출처 : docs.oracle.com / sort 메소드는 Comparable을 상속받은(구현한) 타입을 호출 대상으로 제한합니다.

 

java
닫기
public static <T extends Comparable<? super T>> void sort(List<T> list)

java api 공식 문서에 나와있는 `Collections.sort` 의 정의 부분을 참고하면 아래와 같이 구현되어야 함을 알 수 있습니다. 

  1. `sort` 의 입력 인자값은 `List`여야 한다
  2. `T extends Comparable<T>` : 인자값의 타입은 `Comparable <T>` 인터페이스를 상속(구현) 해야 한다

이어서 Comparable<T> 인터페이스의 구성요소를 살펴보겠습니다.

 

메서드 요약
출처 : docs.oracle.com / Comparable은 compareTo 메소드로만 구성되어 있습니다.

 

Comparable <T> 인터페이스는 `int compareTo(T o)` 메서드 한 개로만 구성되어 있습니다.

따라서 알 수 있는 점은 아래 두 가지 입니다.

  1. `Collections.sort` 메서드의 정렬 방식을 재정의하는 메서드가 바로 `compareTo(T o)`이다
  2. `compareTo(T o)` 메서드만 구현하면 Comparable 인터페이스를 구현한 클래스 타입의 리스트를 인자값으로 넘겨 `Collections.sort`를 사용할 수 있다.

 

Comparable <T> 인터페이스를 구현하는 클래스를 정의하는 예제와 함께 설명하겠습니다.

 

 

구현

Comparable을 구현하는 클래스

Q. 구현 예제 목표
2차원 지표인 x 값, y 값을 나타내는 정수값들이 순차적으로 주어지면,
x 값을 기준으로 우선적으로 정렬하고, 후순위로 y 값을 기준으로 정렬하는 메서드 sort를 구현한다.

EX) `(4, 1), (1, 3), (1, 2), (3, 3)` → `(1, 2), (1, 3), (3, 3), (4, 1)`

 

implement Comparable <T>, 메서드 compareTo 구현

아래 방식은 여러 유형의 변수를 우선순위를 부여하여 정렬하는 구현 과제에서 자주 사용되는 방식입니다.

 

java
닫기
class Pos implements Comparable<Pos> {
int x;
int y;
Pos(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public int compareTo(Pos p) {
// 우선순위인 x를 기준으로 비교 후 y를 비교한다.
if (this.x == p.x) return this.y - p.y;
// x가 동일할 때 y값을 비교한다.
// this.y > p.y인 경우 양의 정수, this가 더 크며, p가 더 작다
// this.y == p.y인 경우 0 : this와 p의 값이 동일하다
// this.y < p.y인 경우 음의 정수, this가 더 작으며, p가 더 크다
else return this.x - p.x;
// x값을 비교한다.
}
}
  1. 인자값으로 입력받을 x 좌표, y 좌표를 하나의 객체로 정의할 클래스를 선언합니다.
  2. `Collections.sort` 메서드, List의 인자값으로 해당 클래스를 집어넣기 위해서 `Comparable <클래스>`를 구현합니다.
  3. 생성자를 통해 입력되는 x, y 값을 객체의 필드로 선언합니다.
  4. 정렬 규칙을 정의한 compareTo 메서드를 정의합니다.
    • `compareTo`(클래스 인스턴스) : 현재의 객체와 인자값의 객체를 비교합니다.
    • return 하는 int 값이 음수 / 양수 / 0 인지를 기준으로 인스턴스 값 간의 크고 작음의 비교 기준을 정의합니다.
      • 음수 : 인자값으로 받은 객체가 더 크다
      • 0 : 현 객체와 인자값으로 받은 객체 값이 동일하다
      • 양수: 인자값으로 받은 객체가 더 작다
    • `compareTo`를 구현 후 `Collections.sort` 사용 시 해당 기준에 맞춰 오름차순으로 정렬합니다.
      • (클래스가 규정하는 작은 값 → 큰 값 순)

 

main(정렬 구현 확인)

java
닫기
class ComparableSort {
public static void main(String[] args) {
ArrayList<Pos> list = new ArrayList<>();
list.add(new Pos(4, 1));
list.add(new Pos(1, 3));
list.add(new Pos(1, 2));
list.add(new Pos(3, 3));
System.out.println(list.get(0).compareTo(list.get(1)));
// out : 3 (index 0이 index 1보다 크다)
System.out.println(list.get(1).compareTo(list.get(2)));
// out : 1 (index 1이 index 2보다 크다)
System.out.println(list.get(2).compareTo(list.get(3)));
// out : -2 (index 2가 index 3보다 작다)
// compareTo 정의 기반 정렬 확인 (작은 값 -> 큰 값의 오름차순)
Collections.sort(list);
for (Pos p : list) System.out.println(p.x+ " "+p.y);
// out
// 1 2
// 1 3
// 3 3
// 4 1
}

 

위의 예시를 보면 의도한 대로 x값이 우선적으로 오름차순 정렬되고, 후순위로 y값이 정렬됨을 확인할 수 있습니다.

compareTo를 변경함에 따라 y값 우선정렬, 내림차순 정렬 등도 가능합니다.

 

 

1. 내림차순 정렬(우선순위 x > y)

java
닫기
class Pos implements Comparable<Pos> {
// .. 생략 ..
@Override
// y값 우선 정렬
public int compareTo(Pos p) {
if (this.x == p.x) return p.y - this.y;
else return p.x - this.x;
}
}
// .. 생략 ..
public static void main(String[] args) {
ArrayList<Pos> list = new ArrayList<>();
list.add(new Pos(4, 1));
list.add(new Pos(1, 3));
list.add(new Pos(1, 2));
list.add(new Pos(3, 3));
Collections.sort(list);
for (Pos p : list) System.out.println(p.x+ " "+p.y);
// out
// 4 1
// 3 3
// 1 3
// 1 2
}

 

2. 오름차순 정렬(우선순위 y > x)

java
닫기
class Pos implements Comparable<Pos> {
// .. 생략 ..
@Override
// y값 우선 정렬
public int compareTo(Pos p) {
if (this.y == p.y) return this.x - p.x;
else return this.y - p.y;
}
}
// .. 예시 결과 출력 생략 ..

 

여기까지 Comparable을 활용한 Collections.sort 정의를 알아봤습니다.

다음 시간에는 Comparator를 들고 오겠습니다.

 

 

# 구현 코드

클릭 시 깃허브로 이동합니다.

반응형