[Java] Comparator.comparing으로 다중 조건 정렬하기

pintegral·2022년 12월 5일
1

Java

목록 보기
1/3
post-thumbnail

0. Test Data

Employee 클래스

public class Employee {
    String name;
    int age;
    double salary;
    long mobile;

    // constructors, getters & setters
}

Employee 배열 생성 및 초기 순서

employees = new Employee[] { ... };
[Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]

1. keyExtractor와 keyComparator를 인자로 받는 comparing()

Definition

두 매개변수 객체의 value가 아닌 key로 비교하여 정렬하는 로직이기 때문에

  • keyExtractor : 정렬 key를 뽑아내는 함수적 인터페이스
  • keyComparator : 정렬 key를 비교하는 함수적 인터페이스

Example

@Test
public void whenComparing_thenSortedByName() {
    Comparator<Employee> employeeNameComparator
      = Comparator.comparing(Employee::getName);
    
    Arrays.sort(employees, employeeNameComparator);
    
    assertTrue(Arrays.equals(employees, sortedEmployeesByName));
}

Result

keyExtractorEmployee::getName으로 받아 직원의 이름 순으로 정렬되었다.

[Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]

2. keyExtractor를 인자로 받는 comparing()

Definition

Example

@Test
public void whenComparingWithComparator_thenSortedByNameDesc() {
    Comparator<Employee> employeeNameComparator
      = Comparator.comparing(
        Employee::getName, (s1, s2) -> {
            return s2.compareTo(s1);
        });
    
    Arrays.sort(employees, employeeNameComparator);
    
    assertTrue(Arrays.equals(employees, sortedEmployeesByNameDesc));
}

Result

keyExtractor로는 Employee::getName을 받고, keyComparator로는 (s1, s2) -> {return s2.compareTo(s1);} 람다식을 받아 직원의 이름 기준 내림차순 정렬되었다.

[Employee(name=Keith, age=35, salary=4000.0, mobile=3924401), 
Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Ace, age=22, salary=2000.0, mobile=5924001)]

3. Comparator.reversed

Definition

원본 정렬을 기준으로 반대로 정렬

Example

@Test
public void whenReversed_thenSortedByNameDesc() {
    Comparator<Employee> employeeNameComparator
      = Comparator.comparing(Employee::getName);
    Comparator<Employee> employeeNameComparatorReversed 
      = employeeNameComparator.reversed();
    Arrays.sort(employees, employeeNameComparatorReversed);
    assertTrue(Arrays.equals(employees, sortedEmployeesByNameDesc));
}

이름 순으로 정렬한 뒤 내림차순으로 정렬되도록 역순 정렬

Result

[Employee(name=Keith, age=35, salary=4000.0, mobile=3924401), 
Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Ace, age=22, salary=2000.0, mobile=5924001)]

4. Comparator에서 null 값 고려하기

Employee 배열에 임의로 null 데이터 2개를 중간에 삽입

4-1. nullsFirst

Definition

Example

@Test
public void whenNullsFirst_thenSortedByNameWithNullsFirst() {
    Comparator<Employee> employeeNameComparator
      = Comparator.comparing(Employee::getName);
    Comparator<Employee> employeeNameComparator_nullFirst
      = Comparator.nullsFirst(employeeNameComparator);
  
    Arrays.sort(employeesArrayWithNulls, 
      employeeNameComparator_nullFirst);
  
    assertTrue(Arrays.equals(
      employeesArrayWithNulls,
      sortedEmployeesArray_WithNullsFirst));
}

Result

[null, 
null, 
Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Keith, age=35, salary=4000.0, mobile=3924401)]

null 데이터 2개가 우선적으로 정렬

4-2. nullsLast

Definition

Example

@Test
public void whenNullsLast_thenSortedByNameWithNullsLast() {
    Comparator<Employee> employeeNameComparator
      = Comparator.comparing(Employee::getName);
    Comparator<Employee> employeeNameComparator_nullLast
      = Comparator.nullsLast(employeeNameComparator);
  
    Arrays.sort(employeesArrayWithNulls, employeeNameComparator_nullLast);
  
    assertTrue(Arrays.equals(
      employeesArrayWithNulls, sortedEmployeesArray_WithNullsLast));
}

Result

[Employee(name=Ace, age=22, salary=2000.0, mobile=5924001), 
Employee(name=John, age=25, salary=3000.0, mobile=9922001), 
Employee(name=Keith, age=35, salary=4000.0, mobile=3924401), 
null, 
null]

null 데이터 2개가 후순위로 정렬

References

Reference (1) - Comparator.comparing (Tistory)
Reference (2) - Comparator.comparing (Baeldung)
References (3) - Comparable vs Comparator (Tistory)

profile
문제를 끝까지 해결하려는 집념의 개발자

0개의 댓글