Stream流基本语法
什么是Stream?
Stream就是将要处理的元素集合看作一种流,在流的过程中借助Stream API对流中的元素进行操作比如:筛选、排序、聚合等。
Stream特性
通过Lambda 表达式对集合进行便利、高效的聚合操作,或者大批量数据操作,Stream不仅可以通过串行的方式实现数据操作,还可以通过并行的方式处理大批量数据,提高数据的处理效率。
Stream优点
- 代码变得更优雅简洁
- 处理大数据并行流要远高于传统批量处理方式
- 有多种聚合操作
代码编写
创建顺序流
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("王武",12L,"男"));
// 顺序流
Stream<User> stream = list.stream();
创建并行流
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("王武",12L,"男"));
// 并行流
Stream<User> stream = list.parallelStream();
顺序流和并行流区别:
顺序流只会有一个主线程执行流操作,并行流内部会用多线程的方式对流执行操作并且顺序会被打乱
- 如果不存在线程安全,并且是数据量较大的建议使用并行。
- 相反数据量比较小的建议使用顺序流,顺序执行会比并行更快,因为创建线程池和其他的资源也是需要时间的。
- 如果对顺序有要求的不建议使用并行,因为并行执行完成,流顺序会被打乱。
filter(过滤)
案例01:过滤出年龄为10岁的人员
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("王武",12L,"男"));
list.stream().filter(t -> t.getAge() == 10).forEach(System.out::println);
结果:User(name=张三, age=10, hha=男)
案例02:过滤出年龄为10岁的人员并且性别为男性的人员
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",10L,"女"));
list.add(new User("王武",10L,"男"));
list.stream().filter(t -> t.getAge() == 10 && t.getHha().equals("男")).forEach(System.out::println);
结果:User(name=张三, age=10, hha=男) User(name=王武, age=10, hha=男)
聚合
min(最小元素)
案例01:返回年龄最小的人员
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("王武",12L,"男"));
String name = list.stream().min(Comparator.comparing(User::getAge)).get().getName();
System.out.println("年龄最小的人员为:" + name);
结果:年龄最小的人员为:张三
max(最大元素)
案例02:找出名字最长的人员
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
String name = list.stream().max(Comparator.comparing(t -> t.getName().length())).get().getName();
System.out.println("名字最长的人员为:"+name);
结果:名字最长的人员为:张三丰
count(总数)
案例03:获取人员中性别为男性的共有多少人
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
long count = list.stream().filter(t -> t.getHha().equals("男")).count();
System.out.println("男性人员共有:"+count);
结果:男性人员共有:2
映射
map:
官方说明-返回由给定函数应用于此流的元素的结果组成的流,其实就是接收一个函数式的参数,并将元素的结果返回一个新流
案例01:返回人员所有的名称
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
List<String> names = list.stream().map(t -> t.getName()).collect(Collectors.toList());
System.out.println(names);
结果:[张三, 李四, 张三丰]
案例02:将男性人员的年龄加一岁
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
List<User> lists = list.stream().filter(b -> b.getHha().equals("男")).map(t -> {
t.setAge(t.getAge() + 1);
return t;
}).collect(Collectors.toList());
System.out.println(lists);
结果:[User(name=张三, age=11, hha=男), User(name=张三丰, age=13, hha=男)]
reduce(累积)
reduce:
可以将一个流合为一个元素,可以对集合求和 乘积 求最大小值等。
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
// 求和
Integer sum = list.stream().reduce(0,Integer::sum);
System.out.println("求和数 = " + sum);
// 乘积
Optional<Integer> chj = list.stream().reduce((x, y) -> x * y);
System.out.println("乘积数 = " + chj.get());
// 最大值
Integer zud = list.stream().reduce(1,Integer::max);
System.out.println("最大数 = " + zud);
// 最小值
Integer zux = list.stream().reduce(1,Integer::min);
System.out.println("最小数 = " + zux);
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
// 求和
long sum = list.stream().map(User::getAge).reduce(0L,Long::sum);
System.out.println("求和 = " + sum);
// 最大值
long reduce = list.stream().map(User::getAge).reduce(1L,Long::max);
System.out.println("求最大年龄 = " + reduce);
结果:
求和数 = 21
乘积数 = 720
最大数 = 6
最小数 = 1
求和 = 33
求最大年龄 = 12
collect(收集)
collect:
对流的一个收集,最后把流变成一个新的集合或者一个值
toList/toSet/toMap
案例01:将过滤后的集合 收集到新的流中
List<Integer> in = Arrays.asList(1,1,2,3,4,5,5,6);
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
List<User> lists = list.stream().filter(t -> t.getHha().equals("男")).collect(Collectors.toList());
System.out.println(lists);
Set<Integer> set = in.stream().collect(Collectors.toSet());
System.out.println(set);
Map<?, User> map = list.stream().filter(t -> t.getHha().equals("男")).collect(Collectors.toMap(User::getName, t -> t));
System.out.println(map);
结果:
[User(name=张三, age=10, hha=男), User(name=张三丰, age=12, hha=男)]
[1, 2, 3, 4, 5, 6]
{张三=User(name=张三, age=10, hha=男), 张三丰=User(name=张三丰, age=12, hha=男)}
统计
- 个数:count
- 平均值:averagingInt、averagingLong、averagingDouble
- 最值:maxBy、minBy
- 求和:summingInt、summingLong、summingDouble
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
// 人员数量
Long count = list.stream().collect(Collectors.counting());
// 平均年龄
Double average = list.stream().collect(Collectors.averagingDouble(User::getAge));
// 最大年龄
Optional<Long> max = list.stream().map(User::getAge).collect(Collectors.maxBy(Long::compare));
// 年龄之和
Long sum = list.stream().collect(Collectors.summingLong(User::getAge));
System.out.println("人员数量:" + count);
System.out.println("平均年龄:" + average);
System.out.println("最大年龄:" + max.get());
System.out.println("年龄之和:" + sum);
结果:
人员数量:3
平均年龄:11.0
最大年龄:12
年龄之和:33
分组
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
// 年龄大于10岁的分为一组
Map<Boolean, List<User>> part = list.stream().collect(Collectors.partitioningBy(t -> t.getAge() > 10));
// 按性别分组
Map<String, List<User>> group1 = list.stream().collect(Collectors.groupingBy(User::getHha));
// 先按性别分组,再按姓名分组
Map<String, Map<String, List<User>>> group2 = list.stream().collect(Collectors.groupingBy(User::getHha, Collectors.groupingBy(t -> t.getName())));
System.out.println("年龄大于10岁的分为一组:" + part);
System.out.println("按性别分组:" + group1);
System.out.println("先按性别分组,再按姓名分组:" + group2);
结果:
年龄大于10岁的分为一组:{false=[User(name=张三, age=10, hha=男)], true=[User(name=李四, age=11, hha=女), User(name=张三丰, age=12, hha=男)]}
按性别分组:{女=[User(name=李四, age=11, hha=女)], 男=[User(name=张三, age=10, hha=男), User(name=张三丰, age=12, hha=男)]}
先按性别分组,再按姓名分组:{女={李四=[User(name=李四, age=11, hha=女)]}, 男={张三=[User(name=张三, age=10, hha=男)], 张三丰=[User(name=张三丰, age=12, hha=男)]}}
joining
案例01:获取集合name字段 并将字段用逗号分隔返回字符串
List<User> list = new ArrayList<>();
list.add(new User("张三",10L,"男"));
list.add(new User("李四",11L,"女"));
list.add(new User("张三丰",12L,"男"));
String collect1 = list.stream().map(t -> t.getName()).collect(Collectors.joining(","));
System.out.println("逗号分隔:"+collect1);
String collect2 = list.stream().map(t -> t.getName()).collect(Collectors.joining("|"));
System.out.println("竖线分隔:"+collect2);
结果:
逗号分隔:张三,李四,张三丰
竖线分隔:张三|李四|张三丰
ps:
一只小菜鸟 一直在学习 从未敢停止