Java 8 为Java8流的每个元素运行lambda并同时计算处理了多少元素,最优雅的方法是什么?

Java 8 为Java8流的每个元素运行lambda并同时计算处理了多少元素,最优雅的方法是什么?,java-8,Java 8,假设我只想处理流一次,而不在lambda之外变异变量,那么为Java 8流的每个元素运行lambda并同时计算处理了多少项,最优雅的方法是什么?我会使用某种reduce操作,如下所示: int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> { if (string.contains("a")) { // process a in any othe

假设我只想处理流一次,而不在lambda之外变异变量,那么为Java 8流的每个元素运行lambda并同时计算处理了多少项,最优雅的方法是什么?

我会使用某种reduce操作,如下所示:

 int howMany = Stream.of("a", "vc", "ads", "ts", "ta").reduce(0, (i, string) -> {
        if (string.contains("a")) {
            // process a in any other way
            return i+1;
        }
        return i;
    }, (left, right) -> null); // override if parallel stream required

    System.out.println(howMany);

这可以通过
peek
函数完成,因为它返回一个由该流的元素组成的流,并在从结果流中消耗元素时对每个元素执行提供的操作

AtomicInteger counter = new AtomicInteger(0);

elements 
  .stream()
  .forEach(doSomething())
  .peek(elem -> counter.incrementAndGet());

int elementsProcessed = counter.get();

使用它可能很有诱惑力

long count = stream.peek(action).count();
而且它可能会起作用。但是,
peek
的操作仅在处理元素时执行,但对于某些流,计数可能在不处理元素的情况下可用。Java 9将抓住这个机会,这使得上面的代码无法对某些流执行
操作

您可以使用不允许走捷径的
收集
操作,例如

long count = stream.collect(
    Collectors.mapping(s -> { action.accept(s); return s; }, Collectors.counting()));

流在单个步骤中进行处理,在调用最终操作时组合所有中间操作,无论您对它们执行多少操作

这样,您就不必担心,因为您的流将立即被处理。但是,对每个流的元素执行某些操作并计算处理的元素数的最佳方法取决于您的目标。 不管怎样,下面的两个示例不会对变量进行变异以执行该计数

这两个示例都创建一个字符串流,对每个字符串执行trim()以删除空格,然后过滤包含某些内容的字符串

例1 使用peek方法对每个筛选的字符串执行一些操作。在这种情况下,只需打印每一个。最后,它只使用count()来获取处理了多少字符串

Stream=
of(“java”,“streams”,“are”,“lazy”,“evaluated”);
长计数=流
.map(字符串::trim)
.filter(s->!s.isEmpty())
.peek(System.out::println)
.count();
System.out.printf(
“\n修剪()操作后的非空字符串数:%d\n\n”,计数);
例2 过滤和映射后使用collect方法将所有处理过的字符串放入列表中。通过这种方式,可以单独打印列表,并从List.size()中获取元素的数量

Stream=
of(“java”,“streams”,“are”,“lazy”,“evaluated”);
列表=流
.map(字符串::trim)
.filter(s->!s.isEmpty())
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.printf(
“\n修剪()操作后的非空字符串数:%d\n\n”,list.size());

并且不在lambdab之外变异变量。不建议为此目的使用
peek
,它甚至不会编译,如果您尝试在终端
forEach
操作后链接
peek
forEach
返回void,建议的代码无法编译。您所说的过程是什么意思
map()
forEach()
?问题没有提到条件处理,但如果这是有意的,则在计数之前使用
过滤器即可。此外,是什么阻止您指定直接合并函数
(左,右)->左+右
,而不是
(左,右)->空
?它不会对连续流造成任何伤害…
long count = stream.collect(Collectors.summingLong(s -> { action.accept(s); return 1; }));
Stream<String> stream = 
       Stream.of(" java", "", " streams", "   are", " lazily ", "evaluated"); 
long count = stream
    .map(String::trim)
    .filter(s -> !s.isEmpty())
    .peek(System.out::println)
    .count();

System.out.printf(
      "\nNumber of non-empty strings after a trim() operation: %d\n\n", count);
Stream<String> stream = 
    Stream.of(" java", "", " streams", "   are", " lazily ", "evaluated"); 
List<String> list = stream
    .map(String::trim)
    .filter(s -> !s.isEmpty())
    .collect(Collectors.toList());

list.forEach(System.out::println);
System.out.printf(
      "\nNumber of non-empty strings after a trim() operation: %d\n\n", list.size());