考虑一个Parent
类,其中包含属性attrib1
,attrib2
和List<Child>
子项及其相应的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中不遵守该条件并获取新列表的所有子对象。
答案 0 :(得分:6)
如果您想接收所有孩子,您需要的是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
列表本身。
答案 1 :(得分:1)
据我所知,您应该为子列表添加额外的过滤器:
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();
}
})
答案 2 :(得分:0)
我知道这个问题差不多有两年了,但希望这个答案可以帮助别人。
有一个名为com.coopstools.cachemonads的库。它扩展了java流(和Optional)类,允许实体的缓存供以后使用。
解决方案可以在以下位置找到:
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());
其中,parent是数组或流。
为清楚起见,缓存方法是存储父母的方法;并且加载方法是让父母退出的原因。如果父级没有子级,则在第一个映射之后将需要一个过滤器来删除空列表。
此库可用于需要对子项执行操作的任何情况,包括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)