java-8 过滤列表而不创建新列表

Posted

技术标签:

【中文标题】java-8 过滤列表而不创建新列表【英文标题】:java-8 filter a list without creating a new list 【发布时间】:2015-10-23 23:22:35 【问题描述】:

我正在寻找在 Java-8 中过滤列表的最简洁方法,使用简单的 lambda Predicate无需创建新列表

这个解决方案尤其不适合,因为toList() 返回一个新的List

List<Person> beerDrinkers = persons.stream()
    .filter(p -> p.getAge() > 16)
    .collect(Collectors.toList());

请注意,以下解决方案也不起作用,因为列表应该是其原始值的clear()ed(但显然,如果您在过滤之前将其清除,则没有什么可过滤的了。 ..):

persons.stream()
    .filter(p -> p.getAge() > 16)
    .forEach((p) -> persons.add(p));

(另外,我更喜欢不涉及使用第三方库或框架的解决方案)

【问题讨论】:

不错的变量名。 :P 查看github.com/wapatesh/fig,很多情况下你可能需要它 【参考方案1】:
beerDrinkers.removeIf(p -> p.getAge() <= 16);

【讨论】:

附注:这可能有一个二次渐近的运行时间(取决于列表的类型),而过滤和收集总是 O(n) @Marco13 它不会与 ArrayList 或 LinkedList 一起使用,但它们是迄今为止最常用的列表。您是否考虑过具体的 List 实现? @JBNizet 抱歉,我认为 ArrayList 的 O(n²),因为 ArrayList 上 remove(E) 的 O(n),但实际上,有一个专门的实现对于ArrayList 中的removeIf,它使用BitSet 首先找出要删除的元素,然后在一次运行中压缩ArrayList 的元素。现在我考虑删除上面的评论(和这条评论),尽管对于 remove(E) 是 O(n) 操作并且使用 removeIfdefault 实现的任何列表仍然适用在Collection 接口中定义的... 无需道歉。不要删除评论。在处理默认方法时问自己这样一个问题很有用,它可能会消除未来读者的疑虑。我自己必须检查文档(和代码)以确保 ArrayList 覆盖了该方法。 @Marco13 我同意 JB Nizet 的观点;这是一个有用的讨论。还可能值得注意的是,使用Iterator 并一次删除一个匹配元素的传统方法可能具有 O(n^2) 性能,至少对于ArrayList

以上是关于java-8 过滤列表而不创建新列表的主要内容,如果未能解决你的问题,请参考以下文章

使用 Lambda 的 Java 8 过滤器数组

具有任何匹配属性的对象的 JAVA 8 过滤器列表

从 java 8 流中的列表中过滤值

Java 8 Stream 按键过滤对象列表。排除列表中的键并获取字符串

SwiftUI:过滤的列表索引与新列表不对应

搜索过滤列表视图后如何开始新的意图?