정렬
정렬 대상 클래스
public class Player { private String name; private int score; public Player(String name, int score) { this.name = name; this.score = score; } // Getters, Setters 생략 }
List<Player> players = new ArrayList<>(); players.add(new Player("Alice", 899)); players.add(new Player("Bob", 982)); players.add(new Player("Chloe", 1090)); players.add(new Player("Dale", 982)); players.add(new Player("Eric", 1018)); //Chloe 가 일등이기 때문에 리스트의 맨 앞으로 나와야하고, Alice 는 꼴등이기 때문에 리스트의 맨 뒤로 보내야합니다.
Comparable 인터페이스
정렬 대상 클래스에 자바에서 기본적으로 제공하고 있는 Comparable 인터페이스를 implement하고 compareTo()를
@Overrice
한다public class Player implements Comparable<Player> { // Fields, Getters, Setters 생략 @Override public int compareTo(Player o) { return o.getScore() - getScore(); } }
메서드를 호출하는 객체가 인자로 넘어온 객체보다 작을 경우에는 음수를 리턴하고, 크기가 동일하다면 0, 클 경우에는 양수를 리턴한다
게이머 랭키 페이지의 경우 높은 점수 순으로 내림 차순 정렬을 원하기 때문에, 인자로 넘어온 게이머의 점수에서 메서드를 호출하는 게이머의 점수를 빼면 됩니다.
예를 들어 인자로 넘어온 게이머의 점수가
982
이고compareTo()
메서드를 호출하는 객체의 점수가1018
이라면,compareTo()
메서드는 음수(982-1018
)를 리턴하게 되며, 이는 곧 메서드를 호출하는 게미머가 인자로 넘어온 게이머보다 작다는 것을 의미합니다. 다시 말해, 메서드를 호출를 호출하는 메서드가 점수가 더 크지만, 객체 자체 비교에서는 인자로 넘어온 게이머보다 작은 객체가 됩니다.Collections.sort() 오버로딩 일부
public static <T extends Comparable<? super T>> void sort(List<T> list) { list.sort(null); }
정렬 결과
Collections.sort(players); System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]
이제
Collections.sort()
메서드에는Comparable
인터페이스를 구현한Comparable
타입의Player
객체의 리스트가 인자로 넘어가기 때문에 더 이상 컴파일 에러가 발생하지 않습니다. 정렬 후 게이머 리스트를 출력해보면 원하는 바와 같이 점수가 제일 높은 Chloe 가 리스트의 맨 앞으로 위치하고, 점수가 제일 낮은 Alice 가 리스트의 맨 뒤에 위치하게 됩니다.
Comparator 객체 사용
정렬 대상 클래스의 코드를 직접 수정하지 않을 경우
객체에 이미 존재하고 있는 정렬 기준과 다른 정렬 기준을 적용할 경우
Arrays.sort() 오버로딩 일부
public static <T> void sort(T[] a, Comparator<? super T> c) { if (c == null) { sort(a); } else { if (LegacyMergeSort.userRequested) legacyMergeSort(a, c); else TimSort.sort(a, 0, a.length, c, null, 0, 0); } }
Collections.sort() 오버로딩 일부
public static <T> void sort(List<T> list, Comparator<? super T> c) { list.sort(c); }
정렬 결과
Comparator<Player> comparator = new Comparator<Player>() { @Override public int compare(Player a, Player b) { return b.getScore() - a.getScore(); } }; Collections.sort(players, comparator); System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]
람다 함수로 정렬
Comparator
객체는 메서드가 하나 뿐인 함수형 인터페이스를 구현하기 때문에 람다 함수로 대체가 가능합니다.
Collections.sort(players, (a, b) -> b.getScore() - a.getScore()); System.out.println(players); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]
Stream으로 정렬
Stream
클래스의sorted()
메서드도Comparator
객체를 인자로 받아 정렬을 해줍니다. 스트림을 사용하면 위에서 살펴본 배열과 리스트의 정렬과 달리 기존 객체의 순서를 변경하지 않고, 새롭게 정렬된 객체를 생성하고자 할 때 사용됩니다
List<Player> sortedPlayers = players.stream() .sorted((a, b) -> b.getScore() - a.getScore()) .collect(Collectors.toList()); System.out.println(sortedPlayers); // [Player(name=Chloe, score=1090), Player(name=Eric, score=1018), Player(name=Bob, score=982), Player(name=Dale, score=982), Player(name=Alice, score=899)]
참고 자료