Java 8 Stream(四、Stream终端操作:forEach()、*Match、find*()、max、min()、reduce()、collect()、toArray()、count())

上文我们已经介绍了Stream中间操作,没看过的同学请出门左转 Java 8 Stream(三、Stream中间操作:filter()、distinct()、skip()、limit()、map()、flatMap()、sorted()、peek())。


文章目录

  • 一、分类
  • 二、介绍
    • (一)遍历
      • 1、forEach()
      • 2、forEachOrdered()
    • (二)匹配
      • 1、anyMatch()
      • 2、noneMatch()
      • 3、allMatch()
    • (三)聚合
      • 1、findAny()
      • 2、findFirst()
      • 3、max()
      • 4、min()
      • 1、reduce()
      • 1、collect()
      • 2、toArray()
      • 3、count()
      • Java 8 Stream

本文我们主要介绍Stream终端操作(Terminal operations)。

一、分类

根据对元素的处理方式,终端操作可分为短路操作(short-circuiting)和非短路操作(non-interfering)。
短路操作: 类似 || 操作符,遇到某些符合条件的元素就可以得到最终结果。短路操作包括anyMatch()、noneMatch()、allMatch()、findAny()、findFirst()。
非短路操作: 类似 && 操作符,必须处理所有元素才能得到最终结果。

二、介绍

(一)遍历

1、forEach()

void forEach(Consumer<? super T> action);

说明: 接受一个函数式接口Consumer为入参并对所有元素执行该函数。

2、forEachOrdered()

void forEachOrdered(Consumer<? super T> action);

说明: 接受一个函数式接口Consumer为入参并按元素顺序对所有元素执行该函数。

下面通过串行流和并行流说明两种遍历方式的区别:

Arrays.asList("1", "2", "3").stream().forEach(System.out::println);    // 1 2 3
Arrays.asList("1", "2", "3").stream().forEachOrdered(System.out::println);    // 1 2 3
Arrays.asList("1", "2", "3").parallelStream().forEach(System.out::println);    // 2 3 1
Arrays.asList("1", "2", "3").parallelStream().forEachOrdered(System.out::println);    // 1 2 3

(二)匹配

1、anyMatch()

boolean anyMatch(Predicate<? super T> predicate);

说明: 接受一个函数式接口Predicate为入参,任何一个元素成功返回true。
示例:

System.out.println(Stream.of("1", "2", "3").anyMatch(x -> x.equals("2")));    // true

2、noneMatch()

boolean noneMatch(Predicate<? super T> predicate);

说明: 接受一个函数式接口Predicate为入参,所有元素失败返回true。
示例:

System.out.println(Stream.of("1", "2", "3").noneMatch(x -> x.equals("4")));    // true

3、allMatch()

boolean allMatch(Predicate<? super T> predicate);

说明: 接受一个函数式接口Predicate为入参,与allMatch()相反,所有元素成功返回true。
示例:

System.out.println(Stream.of("1", "2", "3").allMatch(x -> x instanceof String));    // true

(三)聚合

这四个操作都返回一个Optional对象,这是一个为解决NullPointerException产生的包装类。Optional类将在下一篇为大家介绍。

1、findAny()

Optional<T> findAny();

说明: 返回任何一个元素,在串行流中返回第一个元素,在并行流中返回处理最快那个线程的元素。
示例:

System.out.println(Arrays.asList("1", "2", "3").stream().filter(x -> x instanceof String).findAny().orElse(null));    // 1
System.out.println(Arrays.asList("1", "2", "3").parallelStream().filter(x -> x instanceof String).findAny().orElse(null));    // 2

2、findFirst()

Optional<T> findFirst();

说明: 返回第一个元素,在串行流和并行流中均返回第一个元素。
示例:

System.out.println(Arrays.asList("1", "2", "3").stream().filter(x -> x instanceof String).findFirst().orElse(null));    // 1
System.out.println(Arrays.asList("1", "2", "3").parallelStream().filter(x -> x instanceof String).findFirst().orElse(null));    // 1

3、max()

Optional<T> max(Comparator<? super T> comparator);

说明: 通过Comparator比较器返回最大元素。
示例:

System.out.println(Arrays.asList("1", "2", "3").stream().max((Comparator.comparing(Function.identity()))).orElse(null));    // 3

4、min()

Optional<T> min(Comparator<? super T> comparator);

说明: 通过Comparator比较器返回最小元素。
示例:

System.out.println(Arrays.asList("1", "2", "3").stream().min(String::compareTo).orElse(null));    // 1

(三)规约
将流规约成一个值的操作称为规约操作,熟悉MR编程模型的同学应该很好理解。在函数式编程语言的术语中这个过程被称为折叠(fold)。

1、reduce()

T reduce(T identity, BinaryOperator<T> accumulator);
Optional<T> reduce(BinaryOperator<T> accumulator);
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

说明: 该方法存在两个重载方法,每个重载方法接受一个函数式接口BinaryOperator为入参作为计算规则。
第一个方法的第一个入参为初始值;
第二个方法因没有初始值故返回一个Optional对象避免null;
第三个方法主要用在并行流中(当在串行流中使用时第三个参数不起作用)。在并行流中,流被Fork Join出多个线程并行执行,每个线程均执行第二个方法。而第三个参数函数式接口BinaryOperator则将每个线程的结果连接起来生成一个新的流,最后使用第一个方法进行规约。
示例:

System.out.println(Stream.iterate(0, x -> x + 1).limit(10).reduce(Integer::sum).orElse(0));    // 45
System.out.println(Stream.iterate(0, x -> x + 1).limit(10).reduce(1000, Integer::sum));    // 1045
System.out.println(Stream.iterate(0, x -> x + 1).limit(10).reduce(1000, Integer::sum, Integer::max));	// 1045

(四)收集
收集操作也可以理解为一种高级的规约操作。

1、collect()

<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);

说明: 该方法存在一个重载方法,第二个方法接受一个Collector实例,将流中元素收集成另外一个数据结构。在Collectors静态工厂类中大部分实现调用第一个方法,这几乎满足了我们日常所有操作。
示例:

System.out.println(Stream.iterate(0, x -> x + 1).limit(3).collect(Collectors.toList()));    // [0, 1, 2]

2、toArray()

Object[] toArray();
<A> A[] toArray(IntFunction<A[]> generator);

说明: 该方法存在一个重载方法,第一个方法的实现也是调用了第二个方法传入一个Object数组。
示例:

System.out.println(Arrays.toString(Stream.iterate(0, x -> x + 1).limit(3).toArray(Integer[]::new)));    // [0, 1, 2]

3、count()

long count();

说明: 返回流中元素个数。
示例:

System.out.println(Stream.iterate(0, x -> x + 1).limit(3).count());    // 3

Java 8 Stream

Java 8 Stream(一、Stream简介及创建方式)

Java 8 Stream(二、Stream操作和无限流)

Java 8 Stream(三、Stream中间操作:filter()、distinct()、skip()、limit()、map()、flatMap()、sorted()、peek())

Java 8 Stream(四、Stream终端操作:forEach()、Match、find()、max、min()、reduce()、collect()、toArray()、count())

Java 8 Stream(五、Optional类和Stream调试)

你可能感兴趣的:(Java)