Android

[Android, Kotlin] sortedWith()와 compareBy()를 사용한 collection의 다중 정렬 기준 설정

문제 : 등록한 운송장 리스트의 배송 상태가 업데이트 될 때, 업데이트 된 배송 상태에 따라 리스트의 정렬이 필요했다.

다음과 같은 형태의 데이터를 가지는 TrackingInfoCompany 객체의 List를 정렬해야 한다.

 

data class TrackingInfoCompany {
  val completeYN: String,  // 배송완료 시 "Y", 아니면 "N"
  val time: Long  // 마지막 업데이트 시간 (millisecond 단위)
}

 

정렬 기준은 다음과 같다.

1. 배송 완료의 경우, 업데이트 시간에 관계 없이 가장 인덱스의 뒤에 위치.

(배송 완료 상태의 값끼리는 업데이트 시간 최근 순으로 인덱스 앞 위치)

 

2. 업데이트 시간이 최근 순으로 인덱스의 앞에 위치. 

 

 

해결 : 

이를 해결하기 위해서는 다음과 같은 함수가 필요했다.

1. 여러 개의 정렬 기준을 수행

2. 정렬 기준의 우선순위가 부여되어야 함. (A 기준을 통해 정렬 -> 그 상태에서 B 기준을 통해 정렬)

 

 

이러한 조건을 충족하기 위해 sortedWith()와 인자로 compareBy()를 사용하였다.

 

sortedWith()는 인자로 Comparator를 받아 여러 개의 정렬 기준을 둘 수 있으며, 원본 리스트를 바꾸지 않고 정렬된 리스트를 반환한다.

 

여러 개의 정렬 기준을 설정하는 Comparator는 compareBy()를 통해 정의 할 수 있다.

 

val sortedList = list.sortedWith(
    compareBy(
        { 조건 A }, // 1. 조건 A에 대한 정렬 수행 후,
        { 조건 B }  // 2. 1에서 정렬된 리스트를 기반으로 조건 B에 대한 정렬 수행
    )
)

// list : 원본 리스트
// sortedList : 조건 A, B에 의해 정렬된 리스트

즉, 다음과 같이 원본 리스트 list에 대해 sortedWith()와 compareBy()를 사용하여 내부에 조건 block을 둘 수 있다.

이 때, compareBy()는 오름차순 정렬이다. 내림차순 정렬을 위해서는 compareByDescending()을 사용해야 한다.

 

 

위 sortedWith()와 compareBy()를 사용하여 문제를 해결한다.

 

val newList = list.sortedWith(
    compareBy(
        { it.completeYN }, // 문자열 Y보다 N이 먼저이므로, 오름차순 정렬 시 Y는 N보다 뒤에 위치
        { -(it.time) }
        // 오름차순 정렬이므로, 부호를 -로 변경하여 time의 값이 클수록 값이 작아져 앞에 위치
    )
)

 

가장 먼저 completeYN의 값을 기준으로 오름차순 정렬을 수행한다.

문자열 정렬 시, N은 Y보다 앞에 위치하므로 오름차순 정렬 시 Y(배송완료) 는 자연스럽게 N보다 뒤에 위치하도록 정렬된다.

 

배송완료 여부에 따른 정렬을 수행한 후, 이를 기반으로 업데이트 시간에 따른 정렬을 수행한다.

time의 경우 millisecond 기준이므로 time의 값이 클수록 최근 시간임을 의미한다.

 

그러나 본 정렬의 경우 오름차순 정렬이므로 time의 값이 클수록 뒤에 위치한다.

그러므로 부호를 -로 변경하여 time의 값이 클수록(최근 시간일 수록) 인덱스의 앞에 위치할 수 있게 정렬한다.