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

Java:仅从集合中选择所提供类型的元素,java,collections,Java,Collections,我有一个类型为B和C的元素集合,它们都扩展了a。我需要对集合进行筛选,以便只获得类型为B的元素 除了以下方法外,还有其他方法吗 for (A a : initCollection) { if (a instanceof B) { newCollection.add(a)? } } 感谢您,如果不向类A、B和C添加代码,就没有简单的方法可以做到这一点。 真正的问题是:为什么需要过滤掉特定类型的元素?这与在OOP中使用子类型的想法背道而驰。根据您的示例,我认为这样做没有任何错误。然

我有一个类型为B和C的元素集合,它们都扩展了a。我需要对集合进行筛选,以便只获得类型为B的元素

除了以下方法外,还有其他方法吗

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

感谢您,如果不向类A、B和C添加代码,就没有简单的方法可以做到这一点。
真正的问题是:为什么需要过滤掉特定类型的元素?这与在OOP中使用子类型的想法背道而驰。

根据您的示例,我认为这样做没有任何错误。然而,如果你想获得灵感,你可以使用谷歌的,特别是
Collections2
类,对你的收藏进行功能式过滤。您可以提供自己的谓词,当然可以执行的
实例

Collection<Object> newCollection = Collections2.filter(initCollection, new Predicate<Object>() { 
    public boolean apply(Object o) {
        return !(o instanceof String);
    } 
});
Collection newCollection=Collections2.filter(initCollection,new Predicate(){
公共布尔应用(对象o){
返回!(o字符串的实例);
} 
});

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

Iterator<A> it = initCollection.iterator();
while (it.hasNext()){
   if (it.next() instanceof C) {
      it.remove();
   }
}
Iterator it=initCollection.Iterator();
while(it.hasNext()){
if(C的it.next()实例){
it.remove();
}
}
在其他答案中被提及,但不是具体的解决方案,这比人们意识到的还要简单:

Iterable<B> onlyBs = Iterables.filter(initCollection, B.class);
Iterable onlyBs=Iterables.filter(initCollection,B.class);
它简单而干净,做正确的事情,只创建一个实例,不复制任何内容,并且不会引起任何警告


(不过,
Collections2.filter()
方法没有这种特殊的重载,因此如果您真的想要
集合
,您必须提供
谓词。instanceOf(B.class)
,而生成的集合仍然是
集合
类型)

这是一个老问题,但我想我会加上这个,以防有人发现

您可以使用纯Java 8及其
s来实现这一点

List<B> filtered = listOfA.stream()
    .filter(a -> a instanceof B)
    .map(a -> (B) a)
    .collect(Collectors.toList());
List filtered=listOfA.stream()
.filter(a->a实例或B实例)
.地图(a->(B)a)
.collect(Collectors.toList());

为什么会这样?我有一个超类型集合,当然可以有不同的子类型实例。现在我想要一个准确的班级。为什么不呢?错误在哪里?不是错误。尽管OO纯粹主义者可能会说,对于您想要执行的任何操作,让主集合中的每个对象都实现一个方法来执行(更高级别的对象实现一个noop方法)这就需要频繁地进行性能测试,因此经常会执行您要求的操作。+1对我来说,这样做的愿望似乎是一种代码气味。在某些情况下,它可能是正确的方法,但我认为在大多数情况下,更改设计将是一个更好的选择。@glaz666:如果必须从超级类型中筛选子类型,则暗示超级类型设计不当。情况并非总是如此,但在许多情况下,问题可以不使用反射来解决:例如,使用访问者模式。为什么您不喜欢它现在的制作方式?您也可以等待Java7。我想这可以缩短时间。好的,谢谢。apache的commons集合也可以实现这一点library@glaz:它不仅不是通用的。番石榴(谷歌收藏)是。我不会错过参数化类型。我是谷歌收藏的忠实粉丝。但我看不出谷歌收藏在这个特殊的例子中有什么优势。将会有更多的项目依赖,更多的代码行,更复杂的代码,几乎可以肯定它会更慢。罗曼:我提到番石榴只是作为一种选择;这主要是口味的问题。但您可能会惊讶地注意到,番石榴解决方案提供了更好的性能。OP的解决方案使用原始数据的子集创建新的数据结构;这是许多新的垃圾收集器的工作<另一方面,code>Collections2
提供了原始集合的视图,即没有新的数据结构(我敢打赌,除了小型固定成本支持数据结构之外)。这是提高函数式编程效率的一个很好的例子。@Carl Smotricz:请附上一个代码示例(或至少提及Collection2中的方法),它可以实现您所描述的功能吗?请注意,使用此解决方案,每次迭代overBs时,都会执行过滤逻辑。这可能是一件好事(如果initCollection已更新,并且您只希望ybs反映更改),也可能是一件坏事(如果您希望得到一个副本,或者只将ybs传递给某个迭代多次的代码)。如果需要副本,只需从filter()的输出创建一个集合。