我希望能够实现类似于这样的效果:
items.stream()
.filter(s-> s.contains("B"))
.forEach(s-> s.setState("ok"))
.collect(Collectors.toList());
筛选,然后更改筛选结果的一个属性,最后将结果收集到列表中。但是调试器显示:
无法在基本类型
void
上调用collect(Collectors.toList())
。
我需要使用2个流吗?
我希望能够实现类似于这样的效果:
items.stream()
.filter(s-> s.contains("B"))
.forEach(s-> s.setState("ok"))
.collect(Collectors.toList());
筛选,然后更改筛选结果的一个属性,最后将结果收集到列表中。但是调试器显示:
无法在基本类型
void
上调用collect(Collectors.toList())
。
我需要使用2个流吗?
forEach
是被设计成终止操作的,是的——在调用它之后你不能再做任何事情。
惯用的方式是首先应用变换,然后使用 collect()
将所有内容收集到所需的数据结构中。
变换可以使用 map
进行,该方法专门用于非变异操作。
如果您正在执行非变异操作:
items.stream()
.filter(s -> s.contains("B"))
.map(s -> s.withState("ok"))
.collect(Collectors.toList());
其中withState
是一个方法,返回包括提供的更改在内的原始对象的副本。
如果您正在执行副作用:
items.stream()
.filter(s -> s.contains("B"))
.collect(Collectors.toList());
items.forEach(s -> s.setState("ok"))
完全
执行突变副作用,但并非总是如此。 - Grzegorz Piwowarekpeek()
的规范已经明确说明实现可以优化掉peek()
。 - Brian Goetzpeek()
像OP所要求的那样工作--“像forEach()
一样,但是是一个中间操作”,这样你就可以在流中自由地进行副作用。 但这不是它的目的。 放弃这个想法,你就没问题了。 - Brian Goetz使用map
替换forEach
。
items.stream()
.filter(s-> s.contains("B"))
.map(s-> {s.setState("ok");return s;})
.collect(Collectors.toList());
forEach
和collect
都是终止操作 - 流只能有一个。任何返回Stream<T>
的操作都是中间操作,其他所有操作都是终止操作。
抵制在没有很好的理由的情况下在流内部使用副作用的冲动。创建新列表,然后应用更改:
List<MyObj> toProcess = items.stream()
.filter(s -> s.contains("B"))
.collect(toList());
toProcess.forEach(s -> s.setState("ok"));
peek
是用于副作用的。 - Grzegorz Piwowarekfilter
,distinct
,短路终端操作如count()
,anyMatch()
,findFirst()
等)才能确定。对于像这样的简单情况,这可能是可以接受的,但通常最好避免依赖它。 - Hulkcount
和findFirst
(“在流实现能够优化掉某些或所有元素的生成的情况下(例如使用findFirst这样的短路操作,或者在count()中描述的示例中),对于那些元素不会调用该操作。”),几天后我们就会确定最终版本的措辞是什么。 - HulkforEach
是一个终端操作,这意味着它产生的结果不是流。 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());
另一种方法是使用 peek
,其意图是在遍历每个元素时应用函数(但其主要目的是进行调试):
items.stream()
.filter (s -> s.contains("B"))
.peek (s -> s.setState("ok")) // no need to return a value here
.collect(Collectors.toList());
您不能在同一个流上执行两个终端操作。
您可以在中间操作(例如map
)中设置对象的状态:
List<YourClass> list =
items.stream()
.filter(s-> s.contains("B"))
.map(s-> {
s.setState("ok");
return s;
})
.collect(Collectors.toList());
items.stream()
.filter(s-> s.contains("B"))
.peek(s-> s.setState("ok"))
.collect(Collectors.toList());
Stream peek(Consumer action) Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream. This is an intermediate operation.
For parallel stream pipelines, the action may be called at whatever time and in whatever thread the element is made available by the upstream operation. If the action modifies shared state, it is responsible for providing the required synchronization.
API Note: This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:
Stream.of("one", "two", "three", "four") .filter(e -> e.length() > 3) .peek(e -> System.out.println("Filtered value: " + e)) .map(String::toUpperCase) .peek(e -> System.out.println("Mapped value: " + e)) .collect(Collectors.toList()); Parameters: action - a non-interfering action to perform on the elements as they are consumed
from the stream Returns: the new stream
.peek()
代替.forEach()
items.stream()
.filter(s-> s.contains("B"))
.peek(s-> s.setState("ok"))
.collect(Collectors.toList());
public static void main(String[] args) {
// Create and populate the Test List
List<Object> objectList = new ArrayList<>();
objectList.add("s");
objectList.add(1);
objectList.add(5L);
objectList.add(7D);
objectList.add(Boolean.TRUE);
// Filter by some condition and collect
List<Object> targetObjectList =
objectList.stream().filter(o -> o instanceof String)
.collect(Collectors.toList());
// Check
targetObjectList.forEach(System.out::println);
}
results.forEach(...)
来执行你的副作用。 - Brian Goetzpeek
方法。该方法可用于遍历流中的每个元素,并允许您执行副作用操作,例如打印或记录元素。 - izogfif