2010-02-22 2 views
27

나는 목록 (또는 세트)가 있다고 가정필터와 구글 컬렉션을 사용하여 목록을 정렬

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB"); 

내가 되돌려 ImmutableList (설정)을 좀하고 싶습니다 자연 순서로 정렬/그룹 용어가 시작 용어 있음을 "src"가 첫 번째이고 "assoc"가 두 번째이고 "dest"가 마지막입니다. 용어에 포함되지 않은 용어는 결과 목록에서 제거되어야합니다.

결과는 "srcB", "srcT", "assocX", "destA"입니다.

나는 Iterables.filter 또는 Predicates의 일부 조합으로이 작업을 수행 할 수 있다고 생각하지만 그냥 보지 못했습니다. 제 생각에는 그것을하는 간결한 방법이 있어야합니다.

편집 : 목록 대신 세트가 작동합니다.

답변

32

만큼 그 세 접두사가 관심있는 유일한 일이다, 나는 이런 식으로 뭔가 좋을 것 :

Predicate<String> filter = new Predicate<String>() { 
     @Override 
     public boolean apply(String input) { 
      return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest"); 
     } 
    }; 

    Function<String, Integer> assignWeights = new Function<String, Integer>() { 
     @Override 
     public Integer apply(String from) { 
      if (from.startsWith("src")) { 
       return 0; 
      } else if (from.startsWith("assoc")) { 
       return 1; 
      } else if (from.startsWith("dest")) { 
       return 2; 
      } else { 
       /* Shouldn't be possible but have to do something */ 
       throw new IllegalArgrumentException(from + " is not a valid argument"); 
      } 
     } 
    }; 

    ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
      Ordering.natural().onResultOf(assignWeights).sortedCopy(
        Iterables.filter(testList, filter) 
      ) 
    ); 

이 솔루션은 확실히 믿을 수 없을만큼 잘 당신이 더 접두사를 추가 시작하면 밖으로 확장되지 것을 필터 또는 정렬 기준으로 필터링 할 수 있습니다. 필터와 각 접두사의 가중치를 지속적으로 업데이트해야하기 때문입니다.

+11

다른 경우에는 'return 3'보다 'IllegalArgumentException()'을 새로 throw하는 것이 좋습니다. –

0

내가 원하지 않는 요소를 제거하기 위해 먼저 술어를 사용하고 Comparator을 구현하고 목록을 정렬해야한다고 생각합니다.

12

This Google Collections example을 살펴보십시오.

Function<Fruit, String> getNameFunction = new Function<Fruit, String>() { 
    public String apply(Fruit from) { 
     return from.getName(); 
    } 
}; 

Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction); 

ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
    nameOrdering).addAll(fruits).build(); 

비록 이것이 확실하게 Set를 반환하지만.

0

일반적으로 이렇게 명확한 데이터를 대조하는 것은 좋지 않은 디자인입니다. 귀하의 경우, "assocX"라고 말하면 "assoc"은 "X"와 별개의 의미를 가지지 만 함께 병합합니다.

그래서 두 개의 필드가있는 클래스를 디자인하는 것이 좋습니다. 그런 다음 첫 번째 입력란에서 순서를 만들고 두 번째 입력란에서 순서를 만들 수 있습니다 (예 : # compound()). 인 toString() 메서드를 사용하면이 필드를 문자열로 병합 할 수 있습니다. 보너스로 공유를 통해 메모리 사용량을 크게 줄일 수 있습니다.

그래서 이러한 개체의 목록을 정렬하고 인쇄하려는 경우 toString()을 호출하면됩니다.

관련 문제