1、介绍
概念:Stream是JDK8推出的新特性语法,它允许以声明式方式处理集合数据 。
什么是声明式处理集合数据:在对集合进行例如筛选、排序、聚合、截取等一系列操作时,不需要编码遍历集合处理,调用对应的API编写核心代码即可。
作用:旨在编写更加简洁紧凑的代码风格,提高代码可读性。
2、体验
①过滤出集合中以张
开始的字符串
//编码方式,使用for循环遍历集合
public static void for_way(){
List<String> arrs = Arrays.asList("张三", "李四", "王五","张三丰");
ArrayList<String> target = new ArrayList<>();
for(String name:arrs){
if(name.startsWith("张")){
target.add(name);
}
}
System.out.println(target);
}
//声明式方式,使用stream
public static void stream_way(){
List<String> arrs = Arrays.asList("张三", "李四", "王五","张三丰");
List<String> target =arrs.stream().filter(name -> name.startsWith("张")).collect(Collectors.toList());
System.out.println(target);
}
3、Stream初始化
创建/转换生成Stream对象,然后再对Stream对象进行其它操作(筛选、排序、聚合、截取等)。
① 通过集合Collection获取。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = list.stream();
② 通过数组获取。
String[] arr= {"张三","李四","王五"};
Stream<String> stream = Arrays.stream(arr);
③ 直接通过值获取。
Stream<String> stream = Stream.of("张三","李四","王五");
4、Stream转为Collection、Array、String
在对Stream对象进行操作(筛选、排序、聚合、截取等)完成后,需将Stream对象转为集合/数组等,方便程序进行其它处理(如响应前端、插入数据库等)。
① Stream => 数组。
Stream<String> streamStr = Stream.of("张三","李四","王五");
String[] arrs = streamStr.toArray(String[]::new);
//上面的操作相当于
String[] arrsLambda = streamStr.toArray(arrLength -> new String[arrLength]);
//涉及拆箱、装箱操作的转换
Stream<Integer> streamInt = Stream.of(1, 2, 3, 4, 5);
int[] arrsInt = streamInt.mapToInt(arrVal -> arrVal).toArray();
② Stream => List。
Stream<String> streamStr = Stream.of("张三","李四","王五");
//方式一
List<String> list = streamStr.collect(Collectors.toList());
//方式二
ArrayList<String> list2 = streamStr.collect(Collectors.toCollection(ArrayList::new));
③ Stream =>Set。
Stream<String> streamStr = Stream.of("张三","李四","王五");
//方式一
Set<String> set = streamStr.collect(Collectors.toSet());
//方式二
Set<String> set2 = streamStr.collect(Collectors.toCollection(HashSet::new));
④ Stream =>Map。
⑤ Stream => String。
⑥ Stream ->Stack
5、Stream 常用管道操作
1)筛选 filter
filter函数接收Predicate(断定型函数式接口)作为参数,接口返回boolean类型,true代表保留元素,false反之。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = list.stream();
//筛选过滤出偶数
List<Integer> result = stream.filter(val -> val % 2 == 0).collect(Collectors.toList());
System.out.println(result);//[2, 4, 6, 8, 10]
2)去重 distinct
去除集合/数组中重复的元素。
List<String> list = Arrays.asList("张三", "李四", "王五", "李四", "狗蛋");
List<String> result = list.stream().distinct().collect(Collectors.toList());
System.out.println(result);//[张三, 李四, 王五, 狗蛋]
3)截取 limit
截取前面的n个元素。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = list.stream().limit(5).collect(Collectors.toList());
System.out.println(result);//[1, 2, 3, 4, 5]
4)跳过 skip
跳过前面的n个元素。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = list.stream().skip(5).collect(Collectors.toList());
System.out.println(result);//[6, 7, 8, 9, 10]
5)映射 map
遍历并处理加工Stream中的每个元素,然后返回一个新的Stream。
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//Stream中的每个元素+10
List<Integer> newList = list.stream().map(val -> val + 10).collect(Collectors.toList());
System.out.println(newList);//[11, 12, 13, 14, 15]
//Stream中的每个元素转为字符串
List<String> newList2 = list.stream().map(val -> "¥" + String.valueOf(val)).collect(Collectors.toList());
System.out.println(newList2);//[¥1, ¥2, ¥3, ¥4, ¥5]
6)合并多个流 flatMap
7)匹配元素
①是否匹配任一元素:anyMatch
判断Stream中是否存在至少一个元素满足指定的条件。
② 是否匹配所有元素:allMatch
判断Stream中是否所有元素都满足指定的条件。
③ 是否未匹配所有元素:noneMatch
判断Stream中是否所有元素都不满足指定的条件(和allMatch刚好相反)。
List<Integer> list = Arrays.asList(10, 20, 30, 40, 50);
//判断Stream中是否存在至少一个元素>=50
boolean anyMatchRes = list.stream().anyMatch(val -> val >= 50);
System.out.println(anyMatchRes);//true
//判断Stream中是否所有元素>=50
boolean allMatchRes = list.stream().allMatch(val -> val >= 50);
System.out.println(allMatchRes);//false
//判断Stream中是否所有元素都不满足>=60
boolean noneMatchRes = list.stream().noneMatch(val -> val >= 60);
System.out.println(noneMatchRes);//true
8)获取元素
①获取任一元素 :findAny
从Stream中随机选出 一个元素出来,返回一个Optional对象。
② 获取首个元素:findFirst
从Stream中取出首个元素出来,返回一个Optional对象。
Optional也是JDK8的新特性,使用方式可参考:https://blog.csdn.net/xiao_yu_gan/article/details/125661440
。
List<String> list = Arrays.asList("张三", "李四", "王五", "狗蛋");
/**
* 获取Stream中任意元素(不知道为啥获取到的始终是第0个元素)
*/
Optional<String> any = list.stream().findAny();
System.out.println(any.orElse(null));//张三
/**
* 获取Stream中首个元素
*/
Optional<String> first = list.stream().findFirst();
System.out.println(first.orElse(null));//张三
9)归约统计
10)遍历流 forEach
Stream提供了新的forEach方法遍历该流中的每个元素void forEach(Consumer<? super T> action)
。
List<String> list = Arrays.asList("张三", "李四", "王五", "狗蛋");
list.stream().forEach(System.out::println);
//上面的操作相当于
list.stream().forEach((val)-> System.out.println(val));
11)排序 sorted
12)并行处理 parallelStream
6、数值Stream
采用Stream进行数值归约操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低。此时最好是将当流操作为纯数值操作时,这样使用数值流能获得较高的效率。
StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream。