Java8 Stream流简介与使用
流简介:
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果
(来源于网络)。
注意:
如果mapToInt 能解决 就用不用map
jdk8 提供了通用的处理方法 和 具体的方法 如果能用具体的 不用通用的 如: mapToInt 能解决就不用 map
因为这样可以节约类似自动拆装箱的操作 提高性能
- 常见获取流的方式
// 数组获取流
Stream<String> strs1 = Stream.of("1", "2", "3");
String[] strings = {
"1", "2", "3"};
Stream<String> strs2 = Stream.of(strings);
Stream<String> strs3 = Arrays.stream(strings);
// list获取流
List<String> strings1 = Arrays.asList("1", "2", "3");
Stream<String> stream = strings1.stream();
- 流产生序号
// 打印 1 2 3
IntStream.of(1, 2, 3).forEach(System.out::println);
System.out.println("---我是分割线---");
// 打印 3 - 7 包含3 不包含8
IntStream.range(3, 8).forEach(System.out::println);
System.out.println("---我是分割线---");
// 打印 3 - 8 包含3 包含8
IntStream.rangeClosed(3, 8).forEach(System.out::println);
- reduce 根据指定的计算模型将Stream中的值计算得到一个最终结果
List<Integer> integers = Arrays.asList(1, 2, 3, 4);
// 根据指定的计算模型将Stream中的值计算得到一个最终结果
// 当前的作用就是求和 reduce 的参数是一个 BinaryOperator
// 他是BiFunction的一个子类的是两个参数和返回值同类型的一个函数式接口
// 返回值是一个Optional 因为一个流 可能没有元素为空的情况 所以返回的是一个Optional
// 注: 函数式接口与Lambda表达式 不太熟悉的小伙伴(可以参考我以前的博客 Java8常用函数式接口整理 )
Optional<Integer> sum = integers.stream().reduce(Integer::sum);
// 注:对Optional 可以参考我以前的博客 Java8 Optional的使用及方法介绍 )
sum.ifPresent(System.out::println);
System.out.println("---我是分割线---");
// 重载的一个reduce方法多了一个 T identity 参数, 相当于初始值一样的作用
// 应为有初始值得存在 所以返回值 不会为空 所以直接返回了 Integer类型
Integer reduce = integers.stream().reduce(0, Integer::sum);
System.out.println("reduce = " + reduce);
- forEach遍历
Stream<String> strs = Stream.of("hello", "world", "hello world");
String[] strings = strs.toArray(String[]::new);
Arrays.asList(strings).forEach(System.out::println);
- 流变成List/Set/Array/String(简单方法)
Stream<String> strs = Stream.of("hello", "world", "hello world");
// 流 => Array
Object[] objects = strs.toArray();
// 流 => ArrayList
List<String> collect1 = strs.collect(Collectors.toList());
// 流 => Set
List<String> collect1 = strs.collect(Collectors.toSet());
// 流 => LinkedList
List<String> collect = strs.collect(Collectors.toCollection(LinkedList::new));
// 流 => String
Stream<String> strs = Stream.of("hello", "world", "hello world");
// joining 参数: 间隔符
String collect1 = strs.collect(Collectors.joining("+"));
strs = Stream.of("hello", "world", "hello world");
// joining 参数1: 间隔符 参数2:字符串开头 参数3:字符串结尾
String collect2 = strs.collect(Collectors.joining(",", "<", ">"));
System.out.println("collect1 = " + collect1);
System.out.println("collect2 = " + collect2);
// collect1 = hello+world+hello world
// collect2 = <hello,world,hello world>
- map 替换 将流中的元素替换成另一个元素
// 将字符串转换成大写并输出
// 将流转换成 字符串
List<String> strings = Arrays.asList("hello", "world", "hello world");
// JAVA8之前替换并输出
for (String string : strings) {
String toUpperCase = string.toUpperCase();
System.out.println(toUpperCase);
}
// 现在
strings.stream().map(String::toUpperCase).forEach(System.out::println);
- flatMap 打通
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list1 = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list2 = Arrays.asList(1, 2, 3, 4, 5);
Stream<List<Integer>> list3 = Stream.of(list, list1, list2);
// flatMap 打通
// 相当于 list list1 list2 合并
list3.flatMap(Collection::stream).forEach(System.out::println);
// 相当于 list list1 list2 合并 并且 integer * 2
list3.flatMap(o -> o.stream().map(integer -> integer * 2)).forEach(System.out::println);
- peek
List<Student> collect4 = students.stream().peek(o -> o.setAge(1111)).collect(Collectors.toList());
- 求流中数字参数
IntStream intStream = IntStream.rangeClosed(3, 8);
IntSummaryStatistics intSummaryStatistics = intStream.summaryStatistics();
// 平均值
double average = intSummaryStatistics.getAverage();
// 数量
long count = intSummaryStatistics.getCount();
// 最大值
int max = intSummaryStatistics.getMax();
// 最小值
int min = intSummaryStatistics.getMin();
// 求和
long sum = intSummaryStatistics.getSum();
- parallelStream 并发流 大数据量时使用
- filter 过滤
/*
* limit取前几条
* skip忽略前几天
* filter: 过滤:他的参数是一个Predicate 穿一个参数返回一个布尔值 过滤掉不为true的元素
* distinct 去重
*/
OptionalInt min = Stream.iterate(1, integer -> integer + 1).limit(7).filter(o -> o > 2).mapToInt(i -> i * 2).skip(2).limit(2).distinct().min();
min.ifPresent(System.out::println);
- partitioning分区与grouping分组
Student libai = Student.builder().name("libai").age(18).score(90).build();
Student libai1 = Student.builder().name("libai").age(18).score(90).build();
Student dufu = Student.builder().name("dufu").age(29).score(78).build();
Student baijuyi = Student.builder().name("baijuyi").age(37).score(60).build();
List<Student> students = Arrays.asList(libai, libai1, dufu, baijuyi);
// 按名字分组
Map<String, List<Student>> collect = students.stream().collect(Collectors.groupingBy(Student::getName));
// 按名字分组统计数量
Map<String, Long> collect1 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
// 按名字分组统计平均分
Map<String, Double> collect2 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.averagingDouble(Student::getScore)));
// 分区: 是特殊的一种分组 满足条件的一种 不满足条件的一组
Map<Boolean, List<Student>> collect3 = students.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 60));
System.out.println(collect);
System.out.println(collect1);
System.out.println(collect2);
System.out.println(collect3);
- Collectors 提供了关于Collector的常用的汇聚实现如toList等等 Collectors本身是一个工厂
Stream<String> strs = Stream.of("hello", "world", "hello world");
// 流 => ArrayList
Object[] objects = strs.toArray();
// 如果mapToInt 能解决 就用不用map
// jdk8 提供了通用的处理方法 和 具体的方法 如果能用具体的 不用通用的 如: mapToInt 能解决就不用 map
// 因为这样可以节约类似自动拆装箱的操作 提高性能
Student libai = Student.builder().name("libai").age(18).score(90).build();
Student libai1 = Student.builder().name("libai").age(18).score(90).build();
Student dufu = Student.builder().name("dufu").age(29).score(78).build();
Student baijuyi = Student.builder().name("baijuyi").age(37).score(60).build();
Student baijuyi1 = Student.builder().name("baijuyi").age(37).score(60).build();
List<Student> list = Arrays.asList(libai, libai1, dufu, baijuyi, baijuyi1);
// 接受两个部分结果和合并它们的功能。组合器功能可以从一个参数折叠状态到另一个并返回,或者可以返回一个新的结果容器。
/*
* collect的参数, 是Collector一个接口,他是一个可变的汇聚操作,将输入的元素累计到一个可变的结果容器中容器.
* 他会在所有的元素处理完毕后 将累计的结果转换成一个结果转换成为一个最终的表示(这是一个可选的操作),他支持
* 串行和并行两种方式运行
* Collectors 提供了关于Collector的常用的汇聚实现如toList等等 Collectors本身是一个工厂
*/
// 转List
List<Student> collect = list.stream().collect(Collectors.toList());
collect.forEach(System.out::println);
System.out.println("---------------------");
// 数量
Long collect1 = list.stream().collect(Collectors.counting());
System.out.println("collect1 = " + collect1);
// 数量
long count = list.stream().count();
System.out.println("count = " + count);
System.out.println("---------------------");
// 最小的分数
Optional<Student> collect2 = list.stream().collect(Collectors.minBy(Comparator.comparingInt(Student::getScore)));
Optional<Student> min = list.stream().min(Comparator.comparingInt(Student::getScore));
list.stream().min(Comparator.comparingInt(Student::getScore)).ifPresent(System.out::println);
System.out.println(list.stream().collect(Collectors.averagingInt(Student::getScore)));
System.out.println(list.stream().collect(Collectors.summarizingInt(Student::getScore)));
// 转换字符串
String collect3 = list.stream().map(Student::getName).collect(Collectors.joining());
System.out.println("collect3 = " + collect3);
String collect4 = list.stream().map(Student::getName).collect(Collectors.joining(","));
System.out.println("collect4 = " + collect4);
String collect5 = list.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")"));
System.out.println("collect5 = " + collect5);
// 按名称分组
Map<Integer, Map<String, List<Student>>> collect6 = list.stream().collect(Collectors.groupingBy(Student::getScore, Collectors.groupingBy(Student::getName)));
System.out.println("collect6 = " + collect6);
// 按分数满足80 分区
Map<Boolean, List<Student>> collect7 = list.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 80));
System.out.println("collect7 = " + collect7);
// 按分数满足80 分区 哪结果按分数满足90 分区
Map<Boolean, Map<Boolean, List<Student>>> collect8 = list.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 80, Collectors.partitioningBy(o -> o.getScore() > 90)));
System.out.println("collect8 = " + collect8);
// 统计分数大于80的个数
Map<Boolean, Long> collect9 = list.stream().collect(Collectors.partitioningBy(o -> o.getScore() > 80, Collectors.counting()));
System.out.println("collect9 = " + collect9);
// 按名称分组 每个名字分数最低的数据 collectingAndThen收集后操作 操作就是第二个参数 Function
Map<String, Student> collect10 = list.stream().collect(Collectors.groupingBy(Student::getName,
Collectors.collectingAndThen(Collectors.minBy(Comparator.comparingInt(Student::getScore)), Optional::get)));
// 每个名字分数最低的数据
Map<String, Student> collect11 = list.stream().collect(Collectors.toMap(Student::getName, Function.identity(),
BinaryOperator.minBy(Comparator.comparingInt(Student::getScore))));
System.out.println("collect10 = " + collect10);
System.out.println("collect11 = " + collect11);