java8流图在这里做了什么?

时间:2017-08-08 07:46:01

标签: java sorting java-8 java-stream

我对java8流中map()forEach()方法之间的区别感到困惑。例如,

List<String> strings = Lists.newArrayList("1", "2");
Map<String, String> map = Maps.newHashMap();
strings.stream().map(s->map.put(s, s));
System.out.println(map);

我在这里得到了空输出,但如果我将地图更改为forEach()就像

一样
List<String> strings = Lists.newArrayList("1", "2");
Map<String, String> map = Maps.newHashMap();
strings.stream().forEach(s->map.put(s, s));
System.out.println(map);

我可以

  

{1 = 1,2 = 2}

为什么它没有运行map()方法?它们之间有什么区别?

4 个答案:

答案 0 :(得分:21)

strings.stream().map(s->map.put(s, s));

不执行任何操作,因为在执行终端操作之前不会处理流管道。因此Map仍为空。

向流管道添加终端操作将导致终端操作所需的map.put(s, s)的每个元素执行Stream(某些终端操作只需要一个元素,而其他元素需要所有元素) Stream)。

另一方面,第二个流管道:

strings.stream().forEach(s->map.put(s, s));

以终端操作结束 - forEach - 为Stream的每个元素执行。

尽管如此,两个片段都在滥用Stream。要根据Collection的内容填充MapStream,您应该使用collect(),这可以创建Map或{ {1}}然后根据自己的喜好填充它。 CollectionforEach有不同的目的。

例如,要创建map

Map

答案 1 :(得分:7)

区别在于:

  • forEach()的想法是对基础集合的每个元素“起作用”(通过具有副作用)而
  • map()是关于在每个对象上应用方法并将其结果放入新流

这也是您的stream().map()不会产生某些结果的原因 - 因为您抛出远离map()来电创建的新流!

从这个意义上说,这两种方法的签名告诉你:

void forEach(BiConsumer<? super K,? super V> action)
  

对此地图中的每个条目执行给定操作,直到处理完所有条目

 <R> Stream<R> map(Function<? super T,? extends R> mapper)
  

返回一个流,该流包含将给定函数应用于此流的元素的结果。

并且为了记录:只有map()方法 - 对于流和集合/ Iterables都存在forEach()

答案 2 :(得分:0)

Stream的每个实例方法的文档都说明该方法是中间操作还是终端操作。只有终端操作才会导致对流进行评估。除非下游终端操作需要,否则可以不执行中间操作。

这可以提高效率,尤其是当终端操作是短路操作时,例如findAny()。在找到匹配元素之后,不需要为其他元素执行具有复杂中间操作集的管道。

在您的情况下,forEach()是终端操作;它导致管道被执行。 map()是一个中间操作;除非下游终端操作要求,否则它不必做任何事情。

答案 3 :(得分:-1)

你应该使用

stream().collect(Collectors.toMap(s -> s,s -> s)

...或其他内容,而不是stream().map(...)

相关问题