Java Stream流归纳
前言
Stream 流是什么,有什么作用,为何要引入?
💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖💖
一、Stream 流
第一:
- a sequence of elements from source that supports aggregate operations
- sequence of elements :一个流对外提供一个接口,可以访问到一串特定的数据。流不存储元素,但是可以根据需要进行计算转化
- source:数据来源,如数据结构,数组,文件等
- aggregate operation:聚合操作,流支持像SQL 操作或其他函数式语言的操作,如 filter/map/reduce/find/match/sorted 等
第二:
- pipelining: 很多流操作也是返回一个流
- Internal Iteration: 流操作进行迭代,用户感知不到循环遍历
String [] colors = {"white","black","yellow","blue","green"};
List<String> pList = Arrays.asList(colors);
//采用流方法
count = pList.stream().filter(p->p.length()>5).count();
//采用并行流方法
count = pList.parallelStream().filter(p->p.length()>5).count;
是一个链式的执行过程
流的工作流程:
- 流的创建
- 流的转换,将流转换为其他流的中间操作,可包括多个步骤(惰性操作)
- 流的计算结果。这个操作会强制执行之前的惰性操作。这个步骤以后,流就再也不用了。
1、流的创建
- Collection 接口的 stream 方法
Stream< String > as = new ArrayList< String > ().stream();
Stream< String > hs = new HashSet< String >().stream();还有其他的子类不在举例
- Arrays.stream 可以将数组转为 Stream
Stream< String > b1 = Arrays.stream(“a,b,c,d,e”.split(","),3,5);//选择第三个和第五个元素放到流里面去
-
利用Stream 类进行转化
-of 方法,直接将数组转化
Stream < Integer > c1 = Stream.of(new Integer[5]);
Stream < String > c2 = Stream.of(“a,b,c”.split(","));
Stream< String > c3 = Stream.of(“a”,“b”,“c”);
-empty 方法,产生一个空流
Stream< String > d1 = Stream.empty();
generate 方法,接收一个 Lambda 表达式
Stream< String > e1 = Stream.generate(()->“hello”);
Stream< String > e2 = Stream.generate(Math::random);
iterate 方法,接收一个种子,和一个 Lambda 表达式
Stream < BigInteger > e3 = Stream.iterate(BigInteger.ZERO,n->n.add(BigInteger.ONE));
2、流的转换
Stream 转换
- 从一种流到另外一种流(从一组数据经过计算得到另外一组数据)
- 过滤、去重
- 排序
- 转化
- 抽取、跳过、连接
- 其他
-
过滤 filter
① filter(Predicate<? super T> predicate)
② 接收一个 Lambda 表达式,对每个元素进行判定,符合条件留下Stream<Integer> s1 = Stream.of(1,2,3,4,5); Stream<Integer> s2 = s1.filter(n -> n > 2); s2.forEach(System.out::println); //3,4,5
-
去重distinct
① distinct()
② 对流的元素进行过滤,去除重复,只留下不重复的元素Stream<Integer> s1 = Stream.of(1,1,2,2,3,3); Stream s2 = s1.distinct(); s2.forEach(System.out::println); //1,2,3 如果是复杂对象类型,则distinct方法首先根据对象的hashCode() 方法和equals()方法判断是否相等,来进行去重
-
排序 sorted
① sorted()
② 对流的基本类型包装类元素进行排序Stream<Integer> s1 = Stream.of(3,2,32,344,5); Stream<Integer> s2 = s1.sorted(); s2.forEach(System.out::println); // 对于其他类型,我们还可以给他一个排序规则 String [] colors = {"blue","yellow","red","green"}; Stream< String > s3 = Stream.of(colors).sorted(Comparator.comparing(String::length)); s3.forEach(System.out::println); //或者对象已经实现了 comparable接口,实现了 compareTo ()方法 则,默认sorted()方法会根据compareTo 的规则去比较
-
转化
①map
②利用方法引用对流每个元素进行函数计算
③抽取 limit
④跳过skip// map Stream<Double> s1 = Stream.of(-1.5,2.5,-3.5); Stream<Double> s2 = s1.map(Math::abs); s2.forEach(System.out::println); // limit Stream<Double> s1 = Stream.of(1,2,3,4,5,6,7,8); Stream<Double> s2 = s1.limit(3); s2.forEach(System.out::println); //输出1,2,3 // skip Stream<Double> s1 = Stream.of(1,2,3,4,5,6,7,8,9,10); Stream<Double> s2 = s1.skip(8); s2.forEach(System.out::println); // 跳过8 个元素,输出9,10 //还有其他方法不再展示
3、流的计算
首先认识一下: Optional 类型,为什么引入 Optional 类型
以前: 当我们操作一个空的对象的方法时,会报出 NullPointer Exception 的错误,而 Optional 出现就是解决这一问题,那又是怎么解决的??
-
Optional< T >:
- 一个包装器对象
- 要么包装了类型T 的对象,要么没有包装任何对象(还是 null)
- 如果 T 有值,那么直接返回 T 的对象
- 如果 T 是 null ,那么可以返回一个替代物
-
optional< T> 创建
-
of 方法
-
empty 方法
-
ofNullable 方法,对于对象有可能为空的情况下,安全创建
Optional<String> s1 = Optional.of(new String("abc")); Optional<String> s2 = Optional.empty(); String s3 = null; Optional<String> s4 = Optional.ofNullable(s3); //s3 不为空,s4 就是 s3,否则 s4 就为 Optional.empty() // orElse 方法:当s4 对象为空时,则返回规定的默认值,否则 返回 s4的值,这就弥补了以前对象类型的不足 String s5 = s4.orElse("nice"); String s6 = s1.orElse("good"); System.out.println(s5); System.out.println(s6);
-
-
Optional 使用
- get方法 ,获取值,不安全的方法
- orElse 方法,获取值,如果为null,采用替代物的值
- orElseGet 方法,获取值,如果为null,采用Lambda 表达式的值返回
- orElseThrow 方法,获取值,如果为 null,抛出异常
- ifPresent 方法,判断是否为空,不为空返回 true
- isPresent(Consumer),判断是否为空,如果不为空,则进行后续Consumer 的操作,如果为空,则不进行任何操作
- map(Function) ,将值传递给Function 函数进行计算。如果为空,则不进行计算
流的计算:
- 流的计算
- 简单约简(聚合函数): count / max / min / …
- 自定义约简: reduce
- 查看 / 遍历元素 : iterator / forEach
- 存放到数据结构中
下面分别来看每一种:
流的计算:简单约简(聚合函数)
count(), 计数
max(Comparator) ,最大值,需要比较器
min(Comparator),最小值,需要比较器
findFirst(),找到第一个元素
findAny(),找到任意一个元素(随机的返回一个元素)
anyMatch(Predicate),如有任意一个元素满足 Predicate,返回true
allMatch(Predicate),如果所有元素满足Predicate ,返回 true
noneMatch (Predicate),如果没有元素满足 Predicate ,返回true
流的计算:存放到数据结构中
toArray(),将结果转为数据
collect(Collectors.toList()),将结果转为List
collect(Collectors.toSet()),将结果转为Set
collect(Collectors.toMap()),将结果转为Map
collect(Collectors.joining()),将结果连接起来
流的高阶计算:
分组groupingBy 和 分区 partitionBy
分组后的简约
counting
summing
maxBy
minBy
以上方法均在 java.util.stream.Collectors 中
二、总结
JavaStream 的优点:
- 统一转换元素
- 过滤元素
- 利用单个操作合并元素
- 将元素序列存放到某一个集合中
- 搜索满足某些条件的序列
- 类似SQL操作,遵循 “做什么而非做什么” 原则
- 简化了串行/ 并行的大批量操作