访问流的上一步元素的好方法是什么?
这里的示例从父流(String)开始,并将它们平铺到每个父节点的两个子节点(整数)。在我处理整数儿童(forEach)的那一步,我想"记住"父String是什么(' parentFromPreviousStep'编译错误)。
显而易见的解决方案是为String和Integer引入holder类,并在flatMap中生成这样的holder对象流。但这似乎有点笨拙,我想知道是否有办法访问"以前的元素"在这样的链条中或者传递参数" (没有引入特殊的持有人类)。
List<String> parents = new ArrayList();
parents.add("parentA");
parents.add("parentB");
parents.add("parentC");
parents.stream()
.flatMap(parent -> {
List<Integer> children = new ArrayList<>();
children.add(1);
children.add(2);
return children.stream();
}).forEach(child -> System.out.println(child + ", my parent is: ???" + parentFromPreviousStep));
背景:这实际上发生在Nashorn,其想法是为应用程序提供JavaScript脚本代码,而无需部署Java应用程序。这就是为什么我不想为我的两个业务对象(在这里简化为String和Integer)引入一个特殊的Java holder类。 [上面的Java代码在Nashorn中的编写方式几乎相同,流函数是Java,而不是JavaScript。]
答案 0 :(得分:1)
霍尔格对该问题的评论提供了有价值的信息,并导致以下解决方案。 JDK中SimpleImmutableEntry的存在解决了在这种情况下创建专有持有者类不适合我的问题。 (这是一个社区维基,因为Holger提供了答案。)
Stream.of("parentA", "parentB", "parentC")
.flatMap(parent -> Stream.of(
new AbstractMap.SimpleImmutableEntry<>(1, parent),
new AbstractMap.SimpleImmutableEntry<>(2, parent))
).forEach(child -> System.out.println(child.getKey() + ", my parent is: " + child.getValue()));
答案 1 :(得分:0)
子聚合到父,嗯..闻起来像键值对。 地图!
所以,我用这种方式试了一下。它起作用了。希望这会有所帮助。
parents.stream()
.flatMap(parent -> {
List<Integer> children = new ArrayList<>();
children.add(1);
children.add(2);
Map<String, List<Integer>> stringListMap = new HashMap<String, List<Integer>>();
stringListMap.put(parent, children);
return stringListMap.entrySet().stream();
})
.forEach(entry -> {
entry.getValue().stream().forEach(val -> System.out.println(val + ", my parent is: ???" + entry.getKey()));
});
答案 2 :(得分:0)
这在流的reducer方法中是可能的,如下所示,这段代码实际上为您提供了当前元素和前两个元素的列表。 我有点惊讶这个解决方案不在这篇 baeldung 文章中;
https://www.baeldung.com/java-stream-last-element
public List<Integer> mainFunPreviousAccess(int n) {
Supplier<Integer> s = new Supplier<Integer>() {
int next = 0;
@Override
public Integer get() {
return next++;
}
};
return Stream.generate(s).takeWhile(j -> j <= n).map(j -> List.of(j)).reduce((x,y) -> {
System.out.println("\naccumulator x " + x);
System.out.println("y " + y);
int xs = x.size();
if (xs >= 2) {
return List.of(x.get(xs - 2), x.get(xs -1), y.get(0));
}
return List.of(x.get(0), y.get(0));
}).get();
}
@Adligo :)
答案 3 :(得分:0)
这是同一问题的另一种解决方案,它允许继续使用流,因为这不是通过终端操作完成的;
public void mainFunPreviousAccess2(int n) {
//Stream.generate(s).takeWhile(j -> j <= i).forEach(j -> System.out.println("j " + j));
Supplier<Integer> s = new Supplier<Integer>() {
int next = 0;
@Override
public Integer get() {
return next++;
}
};
Function<Integer, List<Integer>> s2 = new Function<Integer,List<Integer>>() {
Integer m1 = null;
@Override
public List<Integer> apply(Integer t) {
if (m1 == null) {
m1 = t;
return List.of(t);
}
List<Integer> r = List.of(m1, t);
m1 = t;
return r;
}
};
Stream.generate(s).takeWhile(k -> k <= n).map(s2).forEach(k -> System.out.println("hey " + k));
}
@Adligo :)