Stream
是 Java8 的新特性,区别于 IO 的流,它是对容器对象功能的增强,为操作容器对象提供便利、高效的方法的同时,简化代码
[toc]
基本概念 使用流时,通常包括三个基本步骤:创建流 -> 中间操作 -> 终止操作。
流常用的相关接口如下,其中 IntStream
、 LongStream
、DoubleStream
对应三种基本类型(int
, long
, double
,注意不是包装类型),Stream
对应所有剩余类型:
1 2 3 4 5 public interface BaseStream <T, S extends BaseStream <T, S>> extends AutoCloseable public interface IntStream extends BaseStream <Integer, IntStream> public interface DoubleStream extends BaseStream <Double, DoubleStream> public interface LongStream extends BaseStream <Long, LongStream> public interface Stream <T> extends BaseStream <T, Stream<T>>
stream
的几点注意事项:
它不是一种数据结构,只是某种数据源的一个 view,因此对 stream 的任何操作都不会影响真实数据,而是会产生一个新 stream
惰式执行:stream 调用中间操作并不会立即执行,而只是生成一个标记了该操作的新 stream,只有调用终止操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以管道 pipeline 的方式执行,这样可以减少迭代次数。计算完成之后 stream 就会失效。
可消费性:stream 只能被 “消费” 一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成
创建流
创建方法
集合
Collection.stream()、Collection.stream()
数组
Arrays.stream()
数值流
IntStream、LongStream、range、rangeClosed
Random.ints()、Random.longs()、Random.doubles()
自己创建
Stream.generate()、Stream.iterate()
文件
Files.lines()
Pattern
splitAsStream()
Stream.of 创建 使用 Stream.of
静态方法创建
1 Stream<String> stream = Stream.of("A" , "B" , "C" , "D" );
从 Collection 创建 1 2 list.stream(); list.parallelStream();
从数组创建 1 2 int [] intArr = {1 , 2 , 3 , 4 , 5 };IntStream arrayStream = Arrays.stream(intArr);
使用数值流可以减少计算过程中拆箱装箱导致的大量耗时,提高性能。
Stream API 提供了 mapToInt()
、mapToDouble()
、mapToLong()
三种方式将普通 Stream 转换成对应的数值流,同时提供了中间方法 boxed()
将数值流转换为对象流
从文件创建 1 2 Stream<String> lines = Files.lines(Paths.get("/path/to/file.txt" ))
从字符串创建 1 2 3 4 5 6 7 8 9 10 String REGEX = "ee" ; Pattern pattern = Pattern.compile(REGEX); Stream<String> stream = pattern.splitAsStream("aaeebbeecceeddee" ); stream.forEach(System.out::println);
中间操作分为:
无状态(Stateless)操作 :指元素的处理不受之前元素的影响
有状态(Stateful)操作 :指该操作只有拿到所有元素之后才能继续下去
相关方法
含义
无状态操作
map() / mapToXXX()
接受一个函数作为参数。这个函数会被应用到每个元素上,并在新流中将其映射成一个新的元素
flatMap() / flatMapToXXX()
与 map() 类似,一对多,多个流被合并成一个流
filter()
通过设置的条件过滤出元素
peek()
对元素进行遍历处理,与 forEach() 一样,但它是中间操作
有状态操作
distinct()
返回一个元素各异(根据流所生成元素的 hashCode() 和 equals() 方法实现)的流
sorted()
返回排序后的流,可传入自定义的 Comparator
limit()
返回一个不超过给定长度的流
skip()
返回一个扔掉了前 n 个元素的流
map()、filter()、distinct() 1 2 3 4 5 6 7 8 9 10 String str = "good good study and day day up" ;Stream.of(str.split(" " )) .filter(s -> s.length() > 2 ) .map(s -> s.length()) .distinct() .forEach(System.out::println);
flatMap() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 String str = "good good study and day day up" ;Stream.of(str.split(" " )) .flatMap(s -> s.chars().boxed()) .forEach(i -> System.out.println((char ) i.intValue()));
sorted() 1 2 3 4 5 6 7 8 int [] nums = new int []{5 , 1 , -1 , -3 , 0 };nums = IntStream.of(nums) .boxed() .sorted((a, b) -> Math.abs(b) - Math.abs(a)) .mapToInt(a -> Integer.valueOf(a)) .toArray();
peek() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 String str = "good good study and day day up" ;Stream.of(str.split(" " )) .peek(System.out::println) .forEach(System.out::println);
limit() 1 2 3 4 5 6 7 8 new Random ().ints().filter(i -> i > 100 && i < 1000 ).limit(5 ) .forEach(System.out::println);
终止(Terminal)操作 终止操作分为:
短路(Short-circuiting)操作 :指遇到某些符合条件的元素就可以得到最终结果
非短路(Unshort-circuiting)操作 :指必须处理完所有元素才能得到最终结果
相关方法
含义
非短路操作
forEach() / forEachOrdered()
遍历流。对于并行流,forEachOrdered() 保证维持流的顺序
collect()
将流转换为其他形式
toArrary()
转化成一个 Object 数组,对于 IntStream 等基本类型流,返回对应的基本类型数组
reduce()
将流中元素反复结合起来,得到一个值
min() / max() / sum() / count()
获取最小值/最大值/和/元素个数
短路操作
findFirst() / findAny()
返回第一个/任意元素
allMatch() / anyMatch() / noneMatch()
检查所有的元素与规则的匹配情况
forEach() forEach()
不能修改自己包含的本地变量值,也不能使用 break
、return
等提前结束循环
1 2 3 4 5 6 7 Stream<Integer> streamNumbers = Stream.of(1 , 2 , 3 , 4 ); streamNumbers.forEach(System.out::println);
forEachOrdered() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 ); list.parallelStream().forEach(System.out::println); list.parallelStream().forEachOrdered(System.out::println);
collect() toArray() 1 2 3 4 List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 ); Object [] strAryNoArg = list.stream().toArray(); Integer [] strAry = list.stream().toArray(Integer[]::new );
reduce() 将流中元素反复结合。可选参数 identity
作为起始值(返回具体类型)或前两个元素作为起始值(返回 Optional
类型)。字符串拼接、数值的 sum、min、max、average 等可看作特殊的 reduce()
1 2 3 4 5 6 7 8 9 10 11 12 IntStream arrayStream = Arrays.stream(new int []{1 , 2 , 3 , 4 , 5 });int sum = arrayStream.reduce(0 , ((e1, e2) -> e1 + e2));System.out.println(sum); String concat = Stream.of("a" , "B" , "c" , "D" , "e" , "F" ). filter(x -> x.compareTo("Z" ) > 0 ). reduce(String::concat).get(); System.out.println(concat);
min()、max()、sum()、count() min()
、max()
需要传入一个比较器,count()
返回的类型是 long
,sum()
为 IntStream
等数值流的方法
findAny()
、max()
、min()
、reduce()
等方法等返回 Optional
容器,它可能含有某值,或者不包含,使用它是为了避免 NullPointerException
1 2 3 4 5 6 7 8 9 Optional.ofNullable(text).ifPresent(System.out::println); if (text != null ) { System.out.println(text); } return Optional.ofNullable(text).map(String::length).orElse(-1 );return if (text != null ) ? text.length() : -1 ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 List<Integer> list = Arrays.asList(-1 , 2 , -3 , 4 , -5 , 6 , -7 ); int maxAbs = list.stream().max((e1, e2) -> Math.abs(e1) - Math.abs(e2)).get();System.out.println(maxAbs); list = Arrays.asList(-1 , 2 , -3 , 4 , -5 , 6 , -7 ); int minAbs = list.stream().max((e1, e2) -> Math.abs(e1) - Math.abs(e2)).get();System.out.println(minAbs); list = Arrays.asList(-1 , 2 , -3 , 4 , -5 , 6 , -7 ); long counts = list.stream().count();System.out.println(counts); list = Arrays.asList(-1 , 2 , -3 , 4 , -5 , 6 , -7 ); int sum = list.stream().mapToInt(e -> Integer.valueOf(e)).sum();System.out.println(sum);
findFirst()、findAny() 1 2 3 4 5 6 7 8 9 10 11 12 13 Stream<Integer> stream = Stream.of(3 , 1 , 10 , 16 , 8 , 4 , 9 ); System.out.println(stream.findFirst().get()); List<Integer> list = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 ); int result = list.parallelStream().filter(e -> e > 5 ).findAny().get();System.out.println("result = " + result);
anyMatch() 、allMatch()、noneMatch() 1 2 3 4 5 6 7 8 9 10 11 12 Stream<Integer> stream = Stream.of(3 , 1 , 10 , 16 , 8 , 4 , 9 ); System.out.println(stream.anyMatch(s -> s == 2 )); stream = Stream.of(3 , 1 , 10 , 16 , 8 , 4 , 9 ); System.out.println(stream.allMatch(s -> s >= 1 )); stream = Stream.of(3 , 1 , 10 , 16 , 8 , 4 , 9 ); System.out.println(stream.noneMatch(s -> s >= 17 ));
附录: stream
相关的类位于 java.util.stream 包中
InInterfaces
Classes
Enums
参考链接 https://blog.csdn.net/justloveyou_/article/details/79562574
https://blog.csdn.net/MinggeQingchun/article/details/123184273
https://blog.csdn.net/A_art_xiang/article/details/124644564
https://blog.csdn.net/qq_43842093/article/details/128526177