当前位置: 首页 > 知识库问答 >
问题:

无法在一个流中进行筛选->forEach->收集?

商弘义
2023-03-14

我想实现这样的目标:

items.stream()
    .filter(s-> s.contains("B"))
    .forEach(s-> s.setState("ok"))
.collect(Collectors.toList());

筛选,然后从筛选结果中更改属性,然后将结果收集到列表中。然而,调试器说:

无法对基元类型 void 调用 collect(Collectors.toList())。

我需要2个流吗?

共有3个答案

储思聪
2023-03-14

forEach 是一个终端操作,意味着它产生非流结果。forEach 不生成任何内容,收集返回集合。您需要的是一个流操作,它可以根据需要修改元素。此操作是 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());
严阳秋
2023-03-14

将< code>forEach替换为< code>map。

 items.stream()
      .filter(s-> s.contains("B"))
      .map(s-> {s.setState("ok");return s;})
      .collect(Collectors.toList());

<code>forEach</code>和<code>collect</code>都是终端操作-流必须只有一个。返回<code>流的任何内容

施敏达
2023-03-14

< code>forEach被设计成一个终端操作,是的,在你调用它之后你不能做任何事情。

惯用的方法是首先应用转换,然后将所有内容< code>collect()到所需的数据结构。

可以使用为非突变操作设计的映射来执行转换。

如果您正在执行非突变操作:

 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"))
 类似资料:
  • 我的JUnitRunner无法选择具有JBehave中指定的meta标记的场景。 以下是我的故事: 下面是我的运行程序文件: 当我作为JUnit test运行上述类时,没有调用带有烟雾标记的实际测试,也没有执行任何内容。 下面是我在执行上面的代码时得到的结果

  • 我想通过列表中的第一个元素进行过滤,然后通过第二个元素进行分组。 在使用Java Stream获得平均值之前,我过滤了第一个元素,即index。这样做合适吗?

  • 问题内容: 我正在尝试CSS过滤器,但在我的Firefox(15.0)浏览器中不起作用。 HTML: CSS: 问题答案: GrayScale具有使用-moz-filter在Firefox中运行的限制。 要使其正常工作,请使用以下代码段:

  • 我想转换 对此: 不幸的是,我 我该怎么修理呢?

  • 我有两个列表,我必须从它们创建一个地图。首先,我在迭代for loop,其次,我想通过一个stream和collect来映射,但我不知道在这种情况下如何使用collectors.tomap。有可能吗?