nim*_*o23 16 java lambda java-8 java-stream
我希望实现这样的目标:
items.stream()
.filter(s-> s.contains("B"))
.forEach(s-> s.setState("ok"))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
过滤,然后从过滤结果中更改属性,然后将结果收集到列表中.但是,调试器说:
无法
collect(Collectors.toList())在原始类型上调用void.
我需要2个流吗?
Grz*_*rek 17
它forEach被设计成一个终端操作,是的 - 你打电话后你什么也做不了.
惯用的方法是先应用转换,然后将collect()所有内容应用到所需的数据结构.
可以使用map针对非变异操作设计的变换来执行变换.
如果您正在执行非变异操作:
items.stream()
.filter(s -> s.contains("B"))
.map(s -> s.withState("ok"))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
where withState是一个返回原始对象副本的方法,包括提供的更改.
如果您正在执行副作用:
items.stream()
.filter(s -> s.contains("B"))
.collect(Collectors.toList());
items.forEach(s -> s.setState("ok"))
Run Code Online (Sandbox Code Playgroud)
Eug*_*ene 11
替换forEach为map.
items.stream()
.filter(s-> s.contains("B"))
.map(s-> {s.setState("ok");return s;})
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
forEach而collect在这两个终端业务-流必须只有一个.任何返回a Stream<T>的intermediate operation东西都是a ,其他任何东西都是a terminal operation.
抵制在没有充分理由的情况下从流内部使用副作用的冲动。制作新列表,然后应用更改:
List<MyObj> toProcess = items.stream()
.filter(s -> s.contains("B"))
.collect(toList());
toProcess.forEach(s -> s.setState("ok"));
Run Code Online (Sandbox Code Playgroud)
forEach是一个终端操作,意味着它产生非流结果。forEach不产生任何东西并collect返回一个集合。您需要的是根据您的需要修改元素的流操作。此操作可map让您指定要应用于输入流的每个元素的函数并生成转换后的元素流。所以你需要这样的东西:
items.stream()
.filter (s -> s.contains("B"))
.map (s -> { s.setState("ok"); return s; }) // need to return a value here
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
另一种方法是使用peek其意图是将函数应用于遍历的每个元素(但其主要目的是用于调试):
items.stream()
.filter (s -> s.contains("B"))
.peek (s -> s.setState("ok")) // no need to return a value here
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)