2013-03-20 2 views
10

필자는 비슷한 기능을 구현할 수없는 클래스가 있지만 2 개의 필드를 기반으로 정렬해야합니다. 구아바에서 어떻게 이것을 할 수 있습니까?여러 기준으로 구아바 주문을 사용하여 개체 목록 정렬

의 클래스가

class X { 
    String stringValue; 
    java.util.Date dateValue; 
} 

라고하자 내가 '각 내에서 내림차순 첫번째 다음 DATEVALUE에 따라 값 필드를 기준으로 정렬 할이

List<X> lotsOfX; 

의 목록을 가지고 그룹 '값 필드.

public class DateValueSortFunction<X> implements Function<X, Long> { 

    @Override 
     public Long apply(X input) { 
     return input.getDateValue().getTime(); //returns millis time 
     } 
} 

public class StringValueSortFunction<X> implements Function<X, Integer> { 

     @Override 
     public Integer apply(X input) { 
      if(input.getStringValue().equalsIgnoreCase("Something")) 
      return 0; 
      else if(input.getStringValue().equalsIgnoreCase("Something else")) 
      return 1; 
      else 
      return 2; 
     } 
} 
sortedList에서

예상 출력은이

Something 03/18/2013 
Something 03/17/2013 
Something else 03/20/2013 
Something else 03/19/2013 
.... 
:
List<X> sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(dateValueSortFunction).reverse().sortedCopy(lotsOfX)); 
sortedList = ImmutableList.copyOf(Ordering.natural().onResultOf(stringValueSortFunction).sortedCopy(sortedList)); 

기능

는 다음과 같이 정의된다

내가 지금까지 해왔 던 것은

내 접근 방식이 작동하지만 목록을 두 번 통과하는 데 분명히 비효율적입니다. 이 작업을 수행하는 더 좋은 방법이 있습니까?

참고 : GWT 앱에서 이것을 사용하십시오. comparable 구현은 옵션이 아닙니다.

답변

18

Ordering.compound을 원합니다. 당신은 한 성명에서 모든 것을 할 수 ,하지만 난 사용하십시오 :

Ordering<X> primary = Ordering.natural().onResultOf(stringValueSortFunction); 
Ordering<X> secondary = Ordering.natural() 
           .onResultOf(dateValueSortFunction) 
           .reverse(); 
Ordering<X> compound = primary.compound(secondary); 

List<X> sortedList = compound.immutableSortedCopy(lotsOfX); 
+0

이것은 작동합니다. 고맙습니다!! – user949110

+0

거룩한 암소! 이것에 감사드립니다, IF ... IFSE 사례를 많이 구해 줬습니다! 나는 교차 조건의 악몽을 꾼다. – Ethenyl

17

덜 기능,하지만 틀림없이 청소기, 솔루션 :

new Ordering<X>() { 
    public int compare(X x1, X x2) { 
    return ComparisonChain.start() 
     .compare(x1.stringValue, x2.stringValue) 
     .compare(x2.dateValue, x1.dateValue) // flipped for reverse order 
     .result(); 
    } 
}.immutableSortedCopy(listOfXs); 
+0

이 부분을 살펴 보았지만 .compare는 입력을 비교할 수 있다고 생각합니다. 그래서 올바르게 이해한다면,이 경우 문자열을 사전 순으로 정렬 할 것입니까? 하지만 내 자신의 사용자 지정 정렬 기능을 넣어야했습니다. – user949110

+0

맞춤형 비교기를 사용하여'String'을 정렬하려면'compare (x1.stringValue, x2.stringValue, new MyCustomStringComparator())'를 사용할 수 있습니다. –

+0

나는 본다. 글쎄, 한 사람이 다른 사람보다 잘 수행하지 않는 한, 나는 둘 다 괜찮아. 나는 다른 대답이 받아 들일만큼 깨끗하다고 ​​생각한다. – user949110

2

자바 8 간결하게 지정하는 비교기에 대한 방법을 제공합니다 체인 비교기. 함께 새로 도입 List.sort, 당신은 할 수 있습니다 :

lotsOfX.sort(
    Comparator.comparingInt(x -> stringValueSortFunction.apply(x.stringValue)) 
     .thenComparing(x -> x.dateValue, Comparator.reverseOrder())); 

이 물론 목록, 변이합니다 - 당신이 변경되지 않은 원래의 목록을 떠나, 또는에서 비교기를 포장하려면 먼저 복사본을 만들을 불변 사본을 원하면 immutableSortedCopy을 주문하고 사용하십시오.