Java 流中上一步的访问元素或传递元素,如;参数";下一步呢?
访问流的前一个步骤的元素的好方法是什么 这里的示例从父对象流(字符串)开始,并将它们平面映射到每个父对象的两个子对象(整数)。在处理整数子级(forEach)的步骤中,我希望“记住”父字符串是什么(“parentFromPreviousStep”编译错误) 显而易见的解决方案是为一个字符串加上一个整数引入一个holder类,然后在flatMap中生成这样的holder对象流。但这似乎有点笨拙,我想知道是否有办法访问这样一个链中的“前一个元素”或“传递一个参数”(不引入特殊的holder类)Java 流中上一步的访问元素或传递元素,如;参数";下一步呢?,java,java-8,java-stream,Java,Java 8,Java Stream,访问流的前一个步骤的元素的好方法是什么 这里的示例从父对象流(字符串)开始,并将它们平面映射到每个父对象的两个子对象(整数)。在处理整数子级(forEach)的步骤中,我希望“记住”父字符串是什么(“parentFromPreviousStep”编译错误) 显而易见的解决方案是为一个字符串加上一个整数引入一个holder类,然后在flatMap中生成这样的holder对象流。但这似乎有点笨拙,我想知道是否有办法访问这样一个链中的“前一个元素”或“传递一个参数”(不引入特殊的holder类) Li
List parents=new ArrayList();
父母。添加(“父母”);
父母。添加(“父母B”);
父母。添加(“父母C”);
parents.stream()
.flatMap(父级->{
List children=new ArrayList();
增加第(1)款;
增加(2);
返回children.stream();
}).forEach(child->System.out.println(child+),我的父项是:???“+parentFromPreviousStep));
背景:这实际上发生在Nashorn,其思想是为应用程序提供JavaScript脚本代码,而无需部署Java应用程序。这就是为什么我不想为我的两个业务对象(这里简化为String和Integer)引入一个特殊的Java holder类。[上面的Java代码几乎可以用Nashorn编写,流函数是Java,而不是JavaScript。]子函数聚合到父函数,嗯。。闻起来像是键值对地图强> 所以,我就这样试过了。它成功了。希望这会有帮助
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()));
});
parents.stream()
.flatMap(父级->{
List children=new ArrayList();
增加第(1)款;
增加(2);
Map stringListMap=新建HashMap();
stringListMap.put(父级、子级);
返回stringListMap.entrySet().stream();
})
.forEach(条目->{
entry.getValue().stream().forEach(val->System.out.println(val+),我的父对象是:???“+entry.getKey());
});
霍尔格对该问题的评论提供了有价值的信息,并引出了以下解决方案。JDK中SimpleImmutableEntry的存在解决了在这种情况下创建专有holder类不是我的选择的问题。(这是一个社区维基,因为霍尔格提供了答案。)
Stream.of(“parentA”、“parentB”、“parentC”)
.flatMap(父对象->流)(
新的AbstractMap.SimpleImmutableEntry(1,父项),
新的AbstractMap.SimpleImmutableEntry(2,父级))
).forEach(child->System.out.println(child.getKey()+),我的父项是:“+child.getValue());
这在流的reducer方法中是可能的,如下所示,此代码实际上为您提供了当前元素和前两个元素的列表。
我有点惊讶,这篇文章中没有这个解决方案
public List mainfonpreviousaccess(int n){
供应商s=新供应商(){
int next=0;
@凌驾
公共整数get(){
返回next++;
}
};
返回流.generate(s).takeWhile(j->j List.of(j)).reduce((x,y)->{
System.out.println(“\n累加器x”+x);
系统输出打印项次(“y”+y);
int xs=x.size();
如果(xs>=2){
返回List.of(x.get(xs-2)、x.get(xs-1)、y.get(0));
}
返回列表(x.get(0),y.get(0));
}).get();
}
@Adligo:)这是同一问题的另一种解决方案,它允许继续使用流,因为这不是通过终端操作完成的
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));
}
public void mainFunPreviousAccess2(int n){
//Stream.generate.takeWhile(j->j System.out.println(“j”+j));
供应商s=新供应商(){
int next=0;
@凌驾
公共整数get(){
返回next++;
}
};
函数s2=新函数(){
整数m1=null;
@凌驾
公共列表应用(整数t){
如果(m1==null){
m1=t;
返回列表(t);
}
列表r=列表(m1,t);
m1=t;
返回r;
}
};
Stream.generate.takeWhile(k->k System.out.println(“hey”+k));
}
@Adligo:)如果要记住关联,需要一个存储该关联的对象。这是自然的,不可避免的方式。直到值类型进入Java场景。关于“笨拙”:你的
flatMap
功能可以简化为parent->Stream.of(1,2)
。我知道,这只是一个例子,但是你必须创建一个列表
并填充它,才能得到一个流
,这一基本假设应该得到纠正。如果要避免使用新的专用holder类,可以使用AbstractMap.SimpleImmutableEntry
来保存两个对象/值。@Holger:这实际上为我回答了这个问题。谢谢你的好建议!我不知道“Stream.of”和“simpleimutableentry”。你正在破坏flatMap
的全部功能。它不打算将List
实例传递到下游。我将Map.Entry
对象传递到下游。在flatMap()
中,它修饰子列表
,并对初始流执行一些map()
工作。我想,这就是我滥用flatMap()的原因。不是吗?您正在返回一个流
。每个条目都包含一个列表。你不是在压平名单。这是最明显的,因为你是一个
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()));
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();
}
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));
}