有没有办法使用一些谓词和java流过滤内部和外部列表?例如:
Class outerObject{
int num;
List<innerObject> innerObjectList;
}
Class innerObject{
int num;
}
List <outerObject> outerObjectList
有没有办法过滤列表,outerObject
列表包含字段num = 10
,相应innerObject
的{{1}}列表是还会按相应的字段outerObject
过滤?
我试过了:
num = 10
但它似乎没有过滤内部列表。
描述性示例:
如果外部列表中有3个对象outerObjectList.stream()
.filter(i -> i.getNum() == 10)
.filter(i -> i.getOrders().stream().anyMatch(s -> getNum() == 10))
.collect(Collectors.toList());
,并且3个对象中的每个对象在num = 10
中都有1个内部对象innerObjectList
那么它应该给我一个3 {{ 1}}列表中每个num = 10
。
答案 0 :(得分:5)
它没有过滤内部列表,因为你在任何时候都没有改变任何元素;您只是将其从顶级列表中删除。
要过滤内部列表,您应该有一个对outerObjects进行操作的.map操作,将它们更改为新的outerObjects,其innerObjectLists本身就是旧对象的过滤版本。
outerObjectList.stream()
.filter(i -> i.getNum() == 10)
.filter(i -> i.getOrders().stream().anyMatch(s -> getNum() == 10))
.collect(Collectors.toList());
让我们稍微分解一下:你有两个流,一个外部流(你在其上调用.filter
,.filter
和.collect
,以及一个内部流,你调用.anyMatch
。所有你最终得到的是外部流的集合,你决不修改它的任何成员(只有流本身的结构,通过删除它们。)你根本不修改内部流;你只是报告它的特征(&#34;它是否有getNum() == 10
的任何内容?&#34;)
如果要过滤内部流,则还有更多工作要做。您实际上可以使用.peek
修改外部流的元素,将其列表更改为&#34;已过滤&#34;版本;或者,如果您想要成为好的和不可变的,可以使用.map
创建新的过滤版本。
对于.map()
方法,您需要有一个lambda来创建一个新的OuterObject,以便:
output.num == input.num
output.innerObjectList == input.innerObjectList.stream().filter(s -> s.getNum() == 10)
这有意义吗?
答案 1 :(得分:0)
当你说&#39;过滤&#39;在流的上下文中,通常意味着过滤流,以便下游操作看到流的子集。我收集的比你真正想要的是根据条件从列表中删除项目。你可以用“偷看”来做到这一点。操作:
public class Outer {
private final int num;
private final List<Inner> inners = new ArrayList<>();
public class Inner {
private final int num;
public Inner(int num) {
this.num = num;
}
public boolean hasNum(int num) {
return this.num == num;
}
}
public Outer(int num) {
this.num = num;
}
public void addInner(int num) {
inners.add(new Inner(num));
}
public void removeInners(int num) {
inners.removeIf(i -> i.hasNum(num));
}
public boolean hasInner(int num) {
return inners.stream().anyMatch(i -> i.hasNum(num));
}
public boolean hasNum(int num) {
return this.num == num;
}
}
@Test
public void testOuter() {
List<Outer> outers = new ArrayList<>();
outers.add(new Outer(1));
outers.add(new Outer(1));
outers.get(1).addInner(5);
outers.get(1).addInner(1);
outers.add(new Outer(2));
outers.add(new Outer(1));
outers.get(3).addInner(1);
outers = outers.stream()
.filter(o -> o.hasNum(1))
.peek(o -> o.removeInners(1))
.collect(Collectors.toList());
assertThat(outers.size(), is(2));
assertFalse(outer.stream().anyMatch(i -> i.hasInner(1)));
}
请注意,我收集后将列表分配回变量。
答案 2 :(得分:0)
如果要就地修改列表(不创建新列表),可以使用tutorial2方法:
outerObjectList.removeIf(i -> i.getNum() != 10);
outerObjectList.forEach(i -> i.getOrders().removeIf(s -> s.getNum() != 10));
此操作不需要Stream API。
答案 3 :(得分:0)
outerObjectList.stream()
.filter(outer -> outer.num == 10)
.map(outerObject -> {
outerObject.innerObjectList= outerObject.innerObjectList.stream().filter(innerObject -> innerObject.num == 10).collect(Collectors.toList());
return outerObject;
})
.collect(Collectors.toList());