我有一个B和C类型的元素集合,它们都扩展了A.我需要过滤集合来获取只有B类型的元素。
有没有办法做到这一点,除了:
for (A a : initCollection) {
if (a instanceof B) {
newCollection.add(a)?
}
}
由于
答案 0 :(得分:11)
Iterable<B> onlyBs = Iterables.filter(initCollection, B.class);
它简单干净,做正确的事情,只创建一个实例并且不复制任何内容,并且不会引起任何警告。
(Collections2.filter()
方法没有这个特殊的重载,所以如果你真的想要一个Collection
,你必须提供Predicates.instanceOf(B.class)
,结果集合仍然可悲属于Collection<A>
类型。)
答案 1 :(得分:4)
根据你的例子,我认为没有任何错误。但是,如果您想获得幻想,可以使用Google的Guava library,特别是Collections2
类,对您的收藏集进行功能样式过滤。你可以提供自己的谓词,当然可以做instanceof
事。
Collection<Object> newCollection = Collections2.filter(initCollection, new Predicate<Object>() {
public boolean apply(Object o) {
return !(o instanceof String);
}
});
答案 2 :(得分:2)
AFAIK,如果不向A,B和C类添加代码,就没有简单的方法可以做到这一点。 真正的问题是:为什么需要过滤掉特定类型的元素?这违背了在OOP中进行子类型的想法。
答案 3 :(得分:0)
如果您不想创建新集合,可以从现有集合中删除奇数元素:
Iterator<A> it = initCollection.iterator();
while (it.hasNext()){
if (it.next() instanceof C) {
it.remove();
}
}
答案 4 :(得分:0)
这是一个老问题,但我想我会添加这个以防万一找到它。
您可以使用纯Java 8及其Stream
来执行此操作。
List<B> filtered = listOfA.stream()
.filter(a -> a instanceof B)
.map(a -> (B) a)
.collect(Collectors.toList());