Java是否有办法在不破坏Stream
链的情况下将函数应用于Stream
的所有元素?我知道我可以致电forEach
,但该方法会返回void
,而不是Stream
。
答案 0 :(得分:24)
有(至少)3种方式。为了示例代码,我假设您要调用2个消费者方法methodA
和methodB
:
一个。使用peek()
:
list.stream().peek(x -> methodA(x)).forEach(x -> methodB(x));
虽然文档说只使用它进行“调试”,但它可以正常工作(现在正在制作中)
B中。使用map()
调用methodA,然后将元素返回到流:
list.stream().map(x -> {method1(x); return x;}).forEach(x -> methodB(x));
这可能是最“可接受”的方法。
℃。在forEach()
中做两件事:
list.stream().forEach(x -> {method1(x); methodB(x);});
这是最不灵活的,可能不适合您的需要。
答案 1 :(得分:4)
您正在寻找Stream
的{{1}}功能。
示例:
map()
答案 2 :(得分:1)
不完全确定breaking the stream chain
的含义,但Stream
上任何返回Stream
的操作都不会中断或消耗< / em>你的流。流被terminal operations
消耗,正如您所指出的那样,forEach
不返回一个Stream<T>
,因此通过执行所有intermediate
来结束流在forEach和forEach本身之前的操作。
在评论中提供的示例中:
myStream.map(obj -> {obj.foo(); return obj;}
你无法用一个班轮真正做到这一点。当然你可以使用方法引用,但是返回的Stream
将是不同的类型(假设foo
返回一个类型):
myStream.map(Obj::foo) // this will turn into Stream<T>, where T is
// the return type of foo, instead of Stream<Obj>
此外,您的map
操作为stateful
,强烈建议不要这样做。您的代码将编译,甚至可能按照您的意愿工作 - 但它可能会失败。 map
操作应为stateless
。
答案 3 :(得分:1)
您拥有的最佳选择是将地图应用于您的信息流。它返回一个流,该流包含将给定的函数应用于此流的元素的结果,例如:
IntStream.rangeClosed(40, 70).limit(20).mapToObj(i -> (Integer) i).map(item->item+3).map(item->item*2)...
(StreamItemABC类型的项目流)
我们正在对流应用几个修改,但是这样我们就不能将任何参数传递给map方法来修复它:
private void applyMethod(ParameterX parX) {
someStreamX().map(n -> methodX(n, parX))...
}
private StreamItemABC methodX (StreamItemABC item, ParameterX parX) {
return notification;
}
答案 4 :(得分:0)
我认为您正在寻找Stream.peek
。但仔细阅读文档,因为它主要是作为调试方法设计的。来自文档:
此方法主要用于支持调试,您希望在元素流经管道中的某个点时查看元素
传递给peek
的操作必须是non interfering。
答案 5 :(得分:0)
我认为最干净的方法是将mutator添加到流中的对象。
例如,
class Victim {
private String tag;
private Victim withTag(String t)
this.tag = t;
return this;
}
}
List<Victim> base = List.of(new Victim());
Stream<Victim> transformed = base.stream().map(v -> v.withTag("myTag"));
如果您愿意(并且有很多意愿),可以使用withTag方法创建并返回一个新的受害者;这可以使受害者变得一成不变。
答案 6 :(得分:0)
您可以使用map
方法,但是必须创建返回this
的辅助方法。例如:
public class Fluent {
public static <T> Function<T, T> of(Consumer<T> consumer) {
return t -> {
consumer.accept(t);
return t;
};
}
}
并在要调用void
方法时使用它:
list.stream().map(Fluent.of(SomeClass::method));
或者如果您想将其与带有某些参数的方法一起使用:
list.stream().map(Fluent.of(x -> x.method("hello")))