java - 使用 Java 流移除和收集元素

标签 java java-8 java-stream

假设我有一个 Collection 和一个 Predicate 匹配我想从 Collection 中删除的元素。但我不只是想丢弃它们,我想将匹配的元素移动到一个新的集合中。我会做类似 this 的事情在 Java 7 中:

List<E> removed = new LinkedList<>();
for (Iterator<E> i = data.iterator(); i.hasNext();) {
    E e = i.next();
    if (predicate.test(e)) {
        removed.add(e);
        i.remove();
    }
}

我很好奇是否有流/Java 8 方法来做到这一点。 Collections.removeIf()不幸的是,它只是返回一个 boolean(甚至不是删除元素的数量?太糟糕了。)我设想了这样的事情(当然 .removeAndYield(Predicate) 没有'不存在):

List<E> removed = data.removeAndYield(predicate).collect(Collectors.toList());

注意:这个问题的灵感来自 a similar question ;这个问题是关于从集合中删除的项目获取流的更一般情况。正如链接问题中所指出的,命令式解决方案可能更具可读性,但我很好奇流是否可能实现这一点。

编辑: 显然,我们可以将任务分成两个独立的步骤,并假设适当的数据结构将是高效的。问题是这是否可以在任意集合上完成(可能没有有效的 .contains() 等)。

最佳答案

如果您不介意,让我稍微改变一下您的要求。 :-)

期望结果的一个特征是匹配的元素应该在一个集合中结束,而不匹配的元素应该在不同的集合中结束。在 Java-8 之前的可变世界中,考虑获取不匹配元素集合的最简单方法是从原始集合中删除匹配元素。

但是删除——原始列表的修改——是要求的固有部分吗?

如果不是,则可以通过简单的分区操作获得结果:

Map<Boolean, List<E>> map = data.stream().collect(partitioningBy(predicate));

结果映射本质上是两个列表,其中包含匹配(key = true)和非匹配(key = false)元素。

优点是这项技术可以一次性完成,必要时可以并行完成。当然,与从原始列表中删除匹配项相比,这会创建一个不匹配元素的重复列表,但这是为不可变性付出的代价。权衡可能是值得的。

关于java - 使用 Java 流移除和收集元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30042222/

相关文章:

java - 通过 Streams 并行执行多个查询

java - 使用查询或扫描的 DynamoDB 中是否有 'NOT IN' 比较器

java - 使用多个键对 Java 对象进行排序

java - 扁平化列表列表的 3 种方法。有理由更喜欢其中之一吗?

java - 如何从流中仅提取一个允许的元素?

java - 同时过滤和映射一个java流

java - 如何反向选择sql中的列?

java - Libgdx:通过post请求重定向到url

java - 使用 java8 流的规范列表组合

linux - Java 8 Javadoc 与 XJC 警告和错误