Java:仅从集合中选择提供类型的元素

我有一个B和C类型的元素集合,它们都扩展了A.我需要过滤集合以获得只有B类型的元素。

有没有办法做到这一点,除了:

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

谢谢

番石榴在其他答案中被提及,但不是特定的解决方案,这比人们意识到的更简单:

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

它简单而干净,做正确的事情,只创建一个实例并且不复制任何内容,并且不会引起任何警告。

(虽然Collections2.filter()方法没有这个特殊的重载,所以如果你真的想要一个Collection ,你必须提供Predicates.instanceOf(B.class) ,结果集合仍然可能是Collection类型Collection 。)

根据你的例子,我认为这样做没有任何问题。 但是,如果您想获得想象力,可以使用Google的Guava库 ,特别是Collections2类,对您的集合进行function样式过滤。 你可以提供自己的谓词,当然可以做一个instanceof

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

AFAIK,如果不向A,B和C类添加代码,就没有简单的方法。真正的问题是:为什么需要过滤掉特定类型的元素? 这违背了在OOP中进行子类型化的想法。

如果您不想创建新集合,可以从现有集合中删除奇数元素:

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

这是一个老问题,但我想我会添加这个以防万一找到它。

您可以使用纯Java 8及其Stream来完成此操作。

 List filtered = listOfA.stream() .filter(a -> a instanceof B) .map(a -> (B) a) .collect(Collectors.toList());