如何使用 Java 8 个流迭代引用父元素的嵌套循环?
How to iterate nested for loops referring to parent elements using Java 8 streams?
我想使用 java8 streams
迭代嵌套列表,并在第一次匹配时提取列表的一些结果。
不幸的是,如果子元素与过滤器匹配,我还必须从父内容中获取值。
我该怎么做?
java7
Result result = new Result();
//find first match and pupulate the result object.
for (FirstNode first : response.getFirstNodes()) {
for (SndNode snd : first.getSndNodes()) {
if (snd.isValid()) {
result.setKey(first.getKey());
result.setContent(snd.getContent());
return;
}
}
}
java8
response.getFirstNodes().stream()
.flatMap(first -> first.getSndNodes())
.filter(snd -> snd.isValid())
.findFirst()
.ifPresent(???); //cannot access snd.getContent() here
应该是这样的:
编辑:感谢 Holger 指出代码不会在第一个有效的 FirstNode 处停止
response.getFirstNodes().stream()
.filter(it -> {it.getSndNodes().stream().filter(SndNode::isValid).findFirst(); return true;})
.findFirst()
.ifPresent(first -> first.getSndNodes().stream().filter(SndNode::isValid).findFirst().ifPresent(snd -> {
result.setKey(first.getKey());
result.setContent(snd.getContent());
}));
可以找到一个测试here
当你需要这两个值并且想使用flatMap
(当你想执行像findFirst
这样的短路操作时需要),你必须映射到一个包含这两个值的对象
response.getFirstNodes().stream()
.flatMap(first->first.getSndNodes().stream()
.map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd)))
.filter(e->e.getValue().isValid())
.findFirst().ifPresent(e-> {
result.setKey(e.getKey().getKey());
result.setContent(e.getValue().getContent());
});
为了仅使用标准 类,我使用 Map.Entry
作为 Pair 类型,而真正的 Pair 类型可能看起来更简洁。
在此特定用例中,您可以将过滤操作移至内部流
response.getFirstNodes().stream()
.flatMap(first->first.getSndNodes().stream()
.filter(snd->snd.isValid())
.map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd)))
.findFirst().ifPresent(e-> {
result.setKey(e.getKey().getKey());
result.setContent(e.getValue().getContent());
});
有一个巧妙的效果,即只为一个匹配项创建一个 Map.Entry
实例(好吧,应该 为 但即使那么它仍然会创建比第一个变体更少的对象。
我想使用 java8 streams
迭代嵌套列表,并在第一次匹配时提取列表的一些结果。
不幸的是,如果子元素与过滤器匹配,我还必须从父内容中获取值。
我该怎么做?
java7
Result result = new Result();
//find first match and pupulate the result object.
for (FirstNode first : response.getFirstNodes()) {
for (SndNode snd : first.getSndNodes()) {
if (snd.isValid()) {
result.setKey(first.getKey());
result.setContent(snd.getContent());
return;
}
}
}
java8
response.getFirstNodes().stream()
.flatMap(first -> first.getSndNodes())
.filter(snd -> snd.isValid())
.findFirst()
.ifPresent(???); //cannot access snd.getContent() here
应该是这样的:
编辑:感谢 Holger 指出代码不会在第一个有效的 FirstNode 处停止
response.getFirstNodes().stream()
.filter(it -> {it.getSndNodes().stream().filter(SndNode::isValid).findFirst(); return true;})
.findFirst()
.ifPresent(first -> first.getSndNodes().stream().filter(SndNode::isValid).findFirst().ifPresent(snd -> {
result.setKey(first.getKey());
result.setContent(snd.getContent());
}));
可以找到一个测试here
当你需要这两个值并且想使用flatMap
(当你想执行像findFirst
这样的短路操作时需要),你必须映射到一个包含这两个值的对象
response.getFirstNodes().stream()
.flatMap(first->first.getSndNodes().stream()
.map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd)))
.filter(e->e.getValue().isValid())
.findFirst().ifPresent(e-> {
result.setKey(e.getKey().getKey());
result.setContent(e.getValue().getContent());
});
为了仅使用标准 类,我使用 Map.Entry
作为 Pair 类型,而真正的 Pair 类型可能看起来更简洁。
在此特定用例中,您可以将过滤操作移至内部流
response.getFirstNodes().stream()
.flatMap(first->first.getSndNodes().stream()
.filter(snd->snd.isValid())
.map(snd->new AbstractMap.SimpleImmutableEntry<>(first, snd)))
.findFirst().ifPresent(e-> {
result.setKey(e.getKey().getKey());
result.setContent(e.getValue().getContent());
});
有一个巧妙的效果,即只为一个匹配项创建一个 Map.Entry
实例(好吧,应该 为