Java 8 特性 Stream API 详细操作教程

2022年6月15日11:13:51

Stream 流是简化集合和数组操作的一种编程方式,使得集合和数组的操作像水流一样流畅。
更多参考:https://www.yuque.com/zhangshuaiyin/java/java-8-stream-api

下面通过原理 +实战 的方式了解 Stream 的用法。

获取方式

  1. 集合:default Stream stream();
  2. 数组:
    1. Arrays.stream(T[] array);
    2. Stream.of(T… values); (可变参数可以接收数组作为参数)
// 1. 集合Collection<String> list=newArrayList<>();Stream<String> ss= list.stream();// 2. 数组String[] arrs=newString[]{"Java","Python","C"};Stream<String> arrs1=Arrays.stream(arrs);Stream<String> arrs2=Stream.of(arrs);

Stream 操作分类

  1. 中间操作(intermediate):通过一系列中间(Intermediate)方法,对数据集进行过滤、检索等数据集的再次处理。

    1. 中间操作的特点是方法返回值还是 Stream 类型,可以继续链式调用其他方法执行操作。
    2. 中间操作是对数据的加工,注意,中间操作是 lazy 操作,并不会立马启动,需要等待终止操作才会执行。
  2. 终止操作(Terminal):通过最终(terminal)方法完成对数据集中元素的处理。

    1. 终止操作的特点是方法返回值为 空 或者 一个其他类型的结果。
    2. 终止操作是 Stream 的启动操作,只有加上终止操作,Stream才会真正的开始执行
  • 无状态(Stateless):指元素的处理不受之前元素的影响;
  • 有状态(Stateful):指该操作只有拿到所有元素之后才能继续下去。
  • 非短路操作(Unshort-circuiting):指必须处理所有元素才能得到最终结果;

短路操作(Short-circuiting):指遇到某些符合条件的元素就可以得到最终结果,如 A || B,只要A为true,则无需判断B的结果。

Java 8 特性 Stream API 详细操作教程 测试集合

Stream 中间操作不会自己启动,所以测试中都会加上 forEach 终止操作来启动 Stream 流的执行。

List<String> list=Arrays.asList("Java","","Spring","Mysql","Python","","C++");

中间操作

filter

【中间操作】过滤元素,筛选 Stream 流中符合条件的元素,作为流返回。

  1. 定义:
Stream<T>filter(Predicate<?superT> predicate);
  1. 实例:找出集合中的空元素
list.stream().filter(String::isEmpty).forEach(System.out::println);

map

【中间操作】对 Stream 流中的元素执行指定操作后映射为新的值流返回(会改变之前的集合元素),相当于加工。

  1. 定义:
<R>Stream<R>map(Function<?superT,?extendsR> mapper);
  1. 实例:将集合中的元素变为大写
list.stream().map(String::toUpperCase).forEach(System.out::println);

peek

【中间操作】返回一个由该流的元素组成的流,另外在每个元素上执行提供的操作,因为元素从结果流中被消耗。(Consumer 没有返回值,不会改变原来 Stream 流中的值)

  1. 定义:
Stream<T>peek(Consumer<?superT> action);
  1. 实例:源码中的说明

@apiNote This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:
此方法的存在主要是为了支持调试,您希望在其中查看元素流经管道中的某个点时的情况:

list.stream().filter(e-> e.length()>3).peek(e->System.out.println("Filtered value: "+ e)).map(String::toUpperCase).peek(e->System.out.println("Mapped value: "+ e)).forEach(System.out::println);

limit

【短路有状态中间操作】截取 Stream 流中前 maxSize 个 元素。

  1. 定义:
Stream<T>limit(long maxSize);
  1. 实例:取集合中前 4 个元素。
list.stream().limit(4).forEach(System.out::println);

skip

【有状态中间操作】在丢弃流的前 n 元素后,返回由该流的其余元素组成的流。 如果此流包含少于 n 元素,则将返回一个空流。

  1. 定义:
Stream<T>skip(long n);
  1. 实例:跳过集合中前 4 个元素。
list.stream().skip(4).forEach(System.out::println);

distinct

【有状态中间操作】返回由该流的不同元素(根据Object.equals(Object) )组成的流。

  • 对于有序流,不同元素的选择是稳定的(对于重复元素,保留遇到顺序中最先出现的元素。)
  • 对于无序流,没有稳定性保证。
  1. 定义:
Stream<T>distinct();
  1. 实例:去除集合中重复的元素。
list.stream().distinct().forEach(System.out::println);

sorted

【有状态中间操作】返回由该流的元素组成的流,按自然顺序排序。

  • 如果此流的元素不是 Comparable ,则在执行终端操作时可能会抛出java.lang.ClassCastException 。
  • 对于有序流,排序是稳定的。 对于无序流,没有稳定性保证。
  1. 定义:
Stream<T>sorted();Stream<T>sorted(Comparator<?superT> comparator);
  1. 实例:按照 自然排序/自然排序倒序 集合中的元素。
list.stream().sorted().forEach(System.out::println);// 还可以实现 Comparator 接口来自定义排序规则
list.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);

终止操作

forEach

【终止操作】遍历操作,依次遍历 Stream 流中的元素,并执行给定的行为。

  1. 定义:
voidforEach(Consumer<?superT> action);
  1. 实例:遍历集合中的元素
list.stream().forEach(System.out::println);// 集合只遍历可简写为 Collection 自带的 forEach() 方法// list.forEach(System.out::println);

toArray

【终止操作】返回一个包含此流元素的数组。

  1. 定义:
Object[]toArray();
  1. 实例:将集合转成数组。
list.stream().toArray();// 对于集合可简写为 Collection 自带的 toArray() 方法// list.toArray();

min/max

【终止操作】返回 Stream 流中最小/最大的元素

  1. 定义:
Optional<T>min(Comparator<?superT> comparator);Optional<T>max(Comparator<?superT> comparator);
  1. 实例:返回集合中最小/最大的元素
Optional<String> min= list.stream().min(Comparator.naturalOrder());System.out.println(min.get());Optional<String> max= list.stream().max(Comparator.naturalOrder());System.out.println(max.get());

count

【终止操作】返回此流中元素的计数。

  1. 定义:
longcount();
  1. 实例:统计集合中的元素个数
long size= list.stream().count();// 对于集合可简写为 Collection 自带的 size() 方法// list.size();

reduce

【终止操作】使用提供的标识值和关联累积函数对该流的元素执行归约,并返回归约后的值。

  1. 定义:
Treduce(T identity,BinaryOperator<T> accumulator);Optional<T>reduce(BinaryOperator<T> accumulator);<U>Ureduce(U identity,BiFunction<U,?superT,U> accumulator,BinaryOperator<U> combiner);
  1. 实例:将集合中的元素累加。
String result= list.stream().reduce("",(s1, s2)-> s1+ s2);// JavaSpringMysqlPythonC++Optional<String> result= list.stream().reduce((s1, s2)-> s1+ s2);

collect

【终止操作】将 Stream 流转换为其他形式,该操作主要作为进行中间操作后的可变规约操作。

  1. 定义:
<R>Rcollect(Supplier<R> supplier,BiConsumer<R,?superT> accumulator,BiConsumer<R,R> combiner);<R,A>Rcollect(Collector<?superT,A,R> collector);
  1. 实例:将 List 转成 Set 。
list.stream().collect(Collectors.toSet());// 连接字符串// String result = list.stream().collect(Collectors.joining("-"));

查找与匹配

anyMatch

【短路终止操作】如果流的任何元素与提供的 断言 匹配,则为 true ,否则为 false。

  1. 定义:
booleananyMatch(Predicate<?superT> predicate);
  1. 实例:判断集合中是否存在有长度大于 6 的元素。
boolean result= list.stream().anyMatch(s-> s.length()>6)// false

allMatch

【短路终止操作】Stream 流中所有元素都与提供的 断言匹配,则为 ture,否则为 false。

  1. 定义:
booleanallMatch(Predicate<?superT> predicate);
  1. 实例:判断集合中的元素长度是否都小于等于 6。
boolean result= list.stream().allMatch(s-> s.length()<=6);// true

noneMatch

【短路终止操作】Stream 流中的所有元素都与提供的 断言 不匹配,则返回 true,否则为 false。

  1. 定义:
booleannoneMatch(Predicate<?superT> predicate);
  1. 实例:判断集合中的元素长度是否都不满足大于 6。
boolean result= list.stream().noneMatch(s-> s.length()>6);// true

findFirst

【短路终止操作】返回 Stream 流中第一个元素。

  1. 定义:
Optional<T>findFirst();
  1. 实例:
Optional<String> first= list.stream().findFirst();String result= first.get();// Java

findAny

【短路终止操作】返回 Stream 流中第一个元素。

  • 此操作的行为明显是不确定的; 可以自由选择流中的任何元素。
  • 这是为了在并行操作中实现最大性能;
  • 代价是对同一源的多次调用可能不会返回相同的结果。 (如果需要稳定的结果,请改用findFirst() 。)
  1. 定义:
Optional<T>findAny();
  1. 实例:
Optional<String> first= list.stream().findAny();String result= first.get();// JavaOptional<String> first= list.parallelStream().findAny();String result= first.get();// Python
  • 作者:一壶浊酒伴余生
  • 原文链接:https://blog.csdn.net/Ep_Little_prince/article/details/117957973
    更新时间:2022年6月15日11:13:51 ,共 5237 字。