【问题标题】:Why is IllegalStateException not thrown after calling two terminal operations on the same stream?为什么在同一流上调用两个终端操作后不抛出 IllegalStateException?
【发布时间】:2019-10-06 00:39:04
【问题描述】:

我了解到collect()forEach() 都是流终端操作,在同一个流上调用它们会抛出IllegalStateException。但是,以下代码编译成功,并按升序打印每个 String 的长度。不抛出异常。怎么会这样?

List<String> list = Arrays.asList("ant", "bird", "chimpanzee", "dolphin");
list.stream().collect(Collectors.groupingBy(String::length))
        .forEach((a, b) -> System.out.println(a));

【问题讨论】:

  • 为什么你认为你在原始Stream上调用foreach而不是collect返回的对象?如果collect 不返回任何内容,它还应该如何工作?

标签: java java-stream illegalstateexception


【解决方案1】:

您调用的forEach 方法不是Stream::forEach 方法,而是Map::forEach 方法,因为您在collect(...) 的返回值上调用它,即MapMap::forEach 方法的一个特点是它采用BiConsumer,而不是Consumer。流的 forEach 永远不会接受带有两个参数的 lambda!

所以你只调用了一个终端操作,即流上的collect。在那之后,您再也没有对流进行任何操作(您开始使用返回的Map),这就是为什么没有抛出IllegalStateExcepton

要在同一个流上实际调用两个终端操作,需要先将流放入一个变量中:

List<String> list = Arrays.asList("ant", "bird", "chimpanzee", "dolphin");
Stream<String> stream = list.stream(); // you need this extra variable.
stream.collect(Collectors.groupingBy(String::length));
stream.forEach((a) -> System.out.println(a)); // this will throw an exception, as expected

【讨论】:

    【解决方案2】:

    list.stream() 生成的流由collect 操作使用。但是,作为分组的结果,该操作会根据字符串的大小生成Map&lt;Integer, List&lt;String&gt;&gt;

    然后在collect 生成的Map 的条目上调用forEach,因此不会为后者抛出IllegalStateException

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 1970-01-01
      • 1970-01-01
      • 2021-10-03
      • 1970-01-01
      相关资源
      最近更新 更多