2010-04-27 65 views
4

我有一個B和C類型元素的集合,它們都擴展爲A.我需要過濾集合以獲取僅B類型的元素。Java:從集合中只選擇提供的類型的元素

有沒有辦法做到這一點,除了:

for (A a : initCollection) { 
    if (a instanceof B) { 
    newCollection.add(a)? 
    } 
} 

感謝

+1

你爲什麼不喜歡現在製作的方式? – Roman 2010-04-27 15:19:12

+0

您也可以等待Java7。這可以用[閉包](http://javac.info)來縮短,我想。 – BalusC 2010-04-27 15:24:54

回答

2

據我所知,沒有這樣做無需添加代碼類A,B沒有純的方式,和C. 實問題是:爲什麼你需要過濾出特定類型的元素?它違背了在OOP中進行子分類的想法。

+0

爲什麼會這樣呢?我有一個超級類型的集合,當然可以有不同的子類型實例。現在我想要有確切的課程。爲什麼不?錯在哪裏? – glaz666 2010-04-27 15:19:05

+0

這不是一個錯誤。雖然面向對象的純粹主義者可能會說,無論您想要做什麼操作,都要使主集合中的每個對象實現一種方法來實現它(使用實現noop方法的更高級別的對象),這常常足以執行性能要求你問的很頻繁。 – DJClayworth 2010-04-27 16:39:15

+0

+1這樣做的願望對我來說似乎是一種代碼味道。在某些情況下它可能是正確的方法,但我認爲在大多數情況下,更改設計將是更好的選擇。 – 2010-04-27 17:37:57

4

根據您的示例,我沒有發現任何問題。但是,如果您想要使用Google的Guava library,特別是Collections2,則可以對您的收藏進行功能風格的過濾。你可以提供你自己的謂詞,這當然可以做instanceof的事情。

Collection<Object> newCollection = Collections2.filter(initCollection, new Predicate<Object>() { 
    public boolean apply(Object o) { 
     return !(o instanceof String); 
    } 
}); 
+0

好的,謝謝。同樣可以通過apache的commons-collections庫 – glaz666 2010-04-27 15:21:30

+2

@glaz完成:它只是不通用的。番石榴(谷歌收藏)是。我不會錯過參數化類型。 – BalusC 2010-04-27 15:23:03

+0

我是谷歌收藏的忠實粉絲。但是我並沒有看到谷歌收藏在這個特定例子中可以提供的任何優勢。將會有一個項目依賴項,更多的代碼行,更復雜的代碼,幾乎可以肯定它會變慢。並沒有任何優點。 – Roman 2010-04-27 15:26:20

0

如果您不希望創建新的集合,你可以從現有的去除奇數元素:

Iterator<A> it = initCollection.iterator(); 
while (it.hasNext()){ 
    if (it.next() instanceof C) { 
     it.remove(); 
    } 
} 
11

Guava被提到了在其他的答案,但沒有具體的解決方案,這是連簡單的比人們意識到:

Iterable<B> onlyBs = Iterables.filter(initCollection, B.class); 

這很簡單,乾淨,做正確的事,只創建一個實例,並沒有複製,而不會引起任何警告。

(該Collections2.filter()方法不具有這種特殊的過載,雖然如此,如果你真的想要一個Collection,你必須提供Predicates.instanceOf(B.class)所得徵收仍然是可悲類型Collection<A>的。)

+2

請注意,使用此解決方案時,每次迭代overBs時,都會執行過濾邏輯。這可以是一件好事(如果initCollection已更新,並且只希望B反映這些更改),或者是一件壞事(如果您期待拷貝或僅將某些代碼傳遞給某些遍歷它的代碼)。如果你想要一個副本,只需從filter()的輸出中創建一個集合。 – NamshubWriter 2010-06-23 20:58:03

0

這是一個古老的問題,但我想我會添加這個以防萬一找到它。

可以使用純Java 8及其Stream就做這個。

List<B> filtered = listOfA.stream() 
    .filter(a -> a instanceof B) 
    .map(a -> (B) a) 
    .collect(Collectors.toList()); 
相關問題