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

时间:2010-04-27 15:07:55

标签: java collections

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

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

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

由于

5 个答案:

答案 0 :(得分:11)

在其他答案中提到了{p> Guava,但没有具体的解决方案,这比人们意识到的更简单:

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());