2010-02-22 178 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

在其他情況下,拋出新的IllegalArgumentException()比'return 3'更好。 – 2011-09-30 11:42:50

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」有不同的含義,但是你將它們合併在一起。

所以我建議設計一個有兩個字段的類。然後,您可以在第一個字段上創建排序,在第二個字段上創建另一個排列,並將它們合併(例如Ordering#compound())。使用確實的toString()方法將這些字段合併爲一個字符串。作爲獎勵,這可能通過共享大大減少內存使用量。

所以你會排序這些對象的列表,如果你想打印它們,你只需在它們上面調用toString()。