使用 Java 8 Streams 从列表中仅获取所需的对象
Posted
技术标签:
【中文标题】使用 Java 8 Streams 从列表中仅获取所需的对象【英文标题】:Getting only required objects from a list using Java 8 Streams 【发布时间】:2015-11-14 22:19:42 【问题描述】:考虑一个具有attrib1
、attrib2
和List<Child>
属性的Parent
子类及其对应的getter 和setter。
Child
是另一个类,具有五个属性 attrib1
-attrib5
及其对应的 getter 和 setter。
现在我创建了一个List<Parent>
父级。然后我想过滤掉一个List<Parent>
,条件如下:-Child.Attrib1 > 10
;
所以我通过 Java 8 流创建了以下查询。
parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1() > 10));
但问题是我会得到每个Parent
对象中的所有孩子。在这里,我只想获取List<Child>
中符合给定条件的那些子对象。
我应该如何删除 List 中不符合条件的所有子对象并获取新的 List。
【问题讨论】:
【参考方案1】:如果您想接收所有孩子,您需要的是Stream<Child>
。以下表达式可能会起作用:
parents.stream().flatMap(e -> e.getChildren().stream()).filter(c -> c.getAttrib1() > 10)
这应该返回列表中get属性值大于10的所有父母的所有孩子。
如果您想通过删除所有不符合条件的子元素来更新父列表,您可以执行以下操作:
parents.forEach(p -> p.getChildren().removeIf(c -> c.getAttrib1() > 10));
这不会创建新列表。相反,它会更新 parents
列表本身。
【讨论】:
通过 flatmap ,我将如何获得 ListgetAttrib1() > 10
的父母列表中找到所有孩子。 List<Parent>
出现在哪里? flatMap 正在将父对象中的所有子流合并为一个子流。
我的要求是删除Listparents.removeIf
从列表中删除 Parent
对象(不是从 Child
列表中匹配的子对象)。这就是你想要的吗?【参考方案2】:
据我所知,您应该为子列表添加额外的过滤器:
parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1() > 10)).forEach(e -> e.setChild(e.getChild().stream().filter(c -> c.getAttrib1 > 10).collect(toList())))
如果你还没有setChild:
您可以从列表中删除项目 创建全新的父对象要删除你可以使用迭代器:
parent.stream().filter(e -> e.getChild().stream().anyMatch(c -> c.getAttrib1 > 10))
.forEach(e ->
for(Iterator<Child> it = e.getChild().iterator(); it.hasNext();)
Child cur = it.next();
if(cur.getAttrib1() <= 10) it.remove();
)
【讨论】:
@sibnick:如果没有setChild,有什么办法可以实现。【参考方案3】:我知道这个问题已经有将近 2 年的历史了,但希望这个答案可以对某人有所帮助。
有一个名为 com.coopstools.cachemonads 的库。它扩展了 java 流(和可选)类以允许缓存实体以供以后使用。
可以通过以下方式找到解决方案:
List<Parent> goodParents = CacheStream.of(parents)
.cache()
.map(Parent::getChildren)
.flatMap(Collection::stream)
.map(Child::getAttrib1)
.filter(att -> att > 10)
.load()
.distinct()
.collect(Collectors.toList());
其中,parents 是一个数组或流。
为了清楚起见,缓存方法是存储父母的;加载方法是将父母拉回来的原因。如果父级没有子级,则在第一个映射之后需要一个过滤器来删除空列表。
此库可用于需要对子项执行操作的任何情况,包括 map/sort/filter/etc,但仍需要较旧的实体。
代码可以在https://github.com/coopstools/cachemonads 找到(我在自述文件中包含了你的示例),或者可以从 maven 下载:
<dependency>
<groupId>com.coopstools</groupId>
<artifactId>cachemonads</artifactId>
<version>0.2.0</version>
</dependency>
(或者,gradle,com.coopstools:cachemonads:0.2.0)
【讨论】:
以上是关于使用 Java 8 Streams 从列表中仅获取所需的对象的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Java 8 Streams 中获取 Inputstream?
使用 Java-8 Streams API 将字符串列表转换为 Map
如何使用 jquery 从 asp.net 列表框中仅获取当前选定的选项