Java8 Stream(三):StreamAPI
2022/1/30 22:04:22
本文主要是介绍Java8 Stream(三):StreamAPI,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
初始数据
Animal类
public class Animal{ private String name; private String type; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getType() { return type; } public void setType(String type) { this.type = type; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Animal() { } public Animal(String name, String type, Integer age) { this.name = name; this.type = type; this.age = age; } @Override public String toString() { return "{name='" + name + '\'' + ", type='" + type + '\'' + ", age=" + age + "}"; } }
初始数据
//初始Integer数组 List<Integer> list = Arrays.asList(4, 3, 7, 9, 8, 2, 1); //初始Animal数组 List<Animal> animalList = new ArrayList<>(); animalList.add(new Animal("皮皮", "狗", 5)); animalList.add(new Animal("犇犇", "狗", 1)); animalList.add(new Animal("小六", "狗", 2)); animalList.add(new Animal("咪咪", "猫", 3)); animalList.add(new Animal("胖虎", "猫", 10)); animalList.add(new Animal("来福", "猫", 2));
1 遍历/查找/匹配 foreach/find/match
1.1. forEach 遍历元素
//foreach 遍历输出元素 //遍历初始Integer数组 System.out.println("遍历初始Integer数组:"); list.stream().forEach(System.out::println); //遍历初始Animal数组数组 System.out.println("遍历初始Animal数组:"); animalList.stream().forEach(System.out::println);
输出结果:
遍历初始Integer数组: 4 3 7 9 8 2 1 遍历初始Animal数组: {name='皮皮', type='狗', age=5} {name='犇犇', type='狗', age=1} {name='小六', type='狗', age=2} {name='咪咪', type='猫', age=3} {name='胖虎', type='猫', age=10} {name='来福', type='猫', age=2}
1.2. find 查找
//find 查找 //findFirst 查找初始Integer数组中的第一个 Optional<Integer> findFirstInteger = list.stream().findFirst(); //findFirst 查找初始Integer数组中的第一个 Optional<Animal> findFirstAnimal = animalList.stream().findFirst(); System.out.println("查找初始Integer数组中的第一个:" + findFirstInteger.get()); System.out.println("查找初始Integer数组中的第一个:" + findFirstAnimal.get()); //findAny 查找初始Integer数组中的任意一个(适用于并行流) Optional<Integer> findAnyInteger = list.parallelStream().findAny(); //findAny 查找初始Animal数组中的任意一个(适用于并行流) Optional<Animal> findAnyAnimal = animalList.parallelStream().findAny(); System.out.println("查找初始Integer数组中的任意一个(适用于并行流):" + findAnyInteger.get()); System.out.println("查找初始Animal数组中的任意一个(适用于并行流):" + findAnyAnimal.get());
输出结果:
查找初始Integer数组中的第一个:4 查找初始Integer数组中的第一个:{name='皮皮', type='狗', age=5} 查找初始Integer数组中的任意一个(适用于并行流):8 查找初始Animal数组中的任意一个(适用于并行流):{name='皮皮', type='狗', age=5}
1.3. match 匹配
//match 匹配 //anyMatch 初始Integer数组任意一个满足条件 数值大于6 boolean anyMatchInteger = list.stream().anyMatch(x -> x > 6); //anyMatch 初始Animal数组任意一个满足条件 年龄大于2 boolean anyMatchAnimal = animalList.stream().anyMatch(x -> x.getAge() > 2); System.out.println("初始Integer数组任意一个满足条件 数值大于6:" + anyMatchInteger); System.out.println("初始Animal数组任意一个满足条件 年龄大于2:" + anyMatchAnimal); //allMatch 初始Integer数组全部满足条件 数值大于6 boolean allMatchInteger = list.stream().allMatch(x -> x > 6); //anyMatch 初始Animal数组全部满足条件 年龄大于2 boolean allMatchAnimal = animalList.stream().allMatch(x -> x.getAge() > 2); System.out.println("初始Integer数组全部满足条件 数值大于6:" + allMatchInteger); System.out.println("初始Animal数组全部满足条件 年龄大于2:" + allMatchAnimal);
输出结果:
初始Integer数组任意一个满足条件 数值大于6:true 初始Animal数组任意一个满足条件 年龄大于2:true 初始Integer数组全部满足条件 数值大于6:false 初始Animal数组全部满足条件 年龄大于2:false
2 筛选 filter
//filter 初始Integer数组中全部满足条件 数值大于6 List<Integer> newListInteger = list.stream() .filter(x -> x > 6) .collect(Collectors.toList()); //filter 初始Animal数组中全部满足条件 年龄大于2 List<Animal> newListAnimal = animalList.stream() .filter(x -> x.getAge() > 2) .collect(Collectors.toList()); System.out.println("初始Integer数组中全部满足条件 数值大于6:"); newListInteger.forEach(System.out::println); System.out.println("初始Animal数组中全部满足条件 年龄大于2:"); newListAnimal.forEach(System.out::println);
输出结果:
初始Integer数组中全部满足条件 数值大于6: 7 9 8 初始Animal数组中全部满足条件 年龄大于2: {name='皮皮', type='狗', age=5} {name='咪咪', type='猫', age=3} {name='胖虎', type='猫', age=10}
3 聚合 max/min/count
3.1 max 获取最大元素 min 获取最小元素
//max //max 对初始Integer数组 自然排序 获取最大元素 Optional<Integer> maxInteger1 = list.stream().max(Integer::compareTo); //max 对初始Animal数组 自然排序 获取最大元素 //需要Animal 实现Comparable接口 Optional<Animal> maxAnimal1 = animalList.stream().max(Animal::compareTo); System.out.println("对初始Integer数组 自然排序 获取最大元素:" + maxInteger1.get()); System.out.println("对初始Animal数组 自然排序 获取最大元素:" + maxAnimal1.get()); //max 对初始Integer数组 自定义排序 排除数值9 获取最大元素 Optional<Integer> maxInteger2 = list.stream().max((o1, o2) -> { if (o1 == 9) { return -1; } return o1.compareTo(o2); }); //max 对初始Animal数组 自定义排序 获取最大元素 Optional<Animal> maxAnimal2 = animalList.stream().max((o1, o2) -> { return o1.getAge() - o2.getAge(); }); Optional<Animal> maxAnimal3 = animalList.stream().max(Comparator.comparingInt(Animal::getAge)); System.out.println("对初始Integer数组 自定义排序 排除数值9 获取最大元素:" + maxInteger2.get()); System.out.println("对初始Animal数组 自定义排序 获取最大元素:" + maxAnimal2.get()); System.out.println("对初始Animal数组 自定义排序 获取最大元素:" + maxAnimal3.get());
Animal类修改
public class Animal implements Comparable { ...省略 ...省略 @Override public int compareTo(Object o) { Animal animal = (Animal) o; return this.getAge() - animal.getAge(); } }
输出结果:
对初始Integer数组 自然排序 获取最大元素:9 对初始Animal数组 自然排序 获取最大元素:{name='胖虎', type='猫', age=10} 对初始Integer数组 自定义排序 排除数值9 获取最大元素:8 对初始Animal数组 自定义排序 获取最大元素:{name='胖虎', type='猫', age=10} 对初始Animal数组 自定义排序 获取最大元素:{name='胖虎', type='猫', age=10}
3.2 count 获取元素数量
//count 初始Integer数组 数值大于6元素数量 long countInteger = list.stream() .filter(x -> x > 6) .count(); //count 初始Animal数组 年龄大于2元素数量 long countAnimal = animalList.stream() .filter(x -> x.getAge() > 2) .count(); System.out.println("初始Integer数组 数值大于6元素数量:" + countInteger); System.out.println("初始Animal数组 年龄大于2元素数量:" + countAnimal);
结果输出:
初始Integer数组 数值大于6元素数量:3 初始Animal数组 年龄大于2元素数量:3
4 map 映射
4.1 map 一对一映射
//map 一对一映射 初始Integer数组每个元素+10 List<Integer> mapListInteger = list.stream() .map(x -> x + 10) .collect(Collectors.toList()); System.out.println("一对一映射 初始Integer数组每个元素+10:"); mapListInteger.forEach(System.out::println); //map 一对一映射 初始Animal数组每个名称拼接~~~ List<Animal> mapListAnimal = animalList.stream() .map(x -> { x.setName(x.getName() + "~~~"); return x; }) .collect(Collectors.toList()); System.out.println("一对一映射 初始Animal数组每个名称拼接~~~:"); mapListAnimal.forEach(System.out::println);
结果输出:
一对一映射 初始Integer数组每个元素+10: 14 13 17 19 18 12 11 一对一映射 初始Animal数组每个名称拼接~~~: {name='皮皮~~~', type='狗', age=5} {name='犇犇~~~', type='狗', age=1} {name='小六~~~', type='狗', age=2} {name='咪咪~~~', type='猫', age=3} {name='胖虎~~~', type='猫', age=10} {name='来福~~~', type='猫', age=2}
4.2 flatMap 1对多映射
//flatMapListInteger 一对多映射 初始Integer数组 一个+10,一个-10: List<Integer> flatMapListInteger = list.stream().flatMap(x -> { List<Integer> integers = new ArrayList<>(); integers.add(x + 10); integers.add(x - 10); return integers.stream(); }).collect(Collectors.toList()); System.out.println("一对多映射 初始Integer数组 一个+10,一个-10:"); flatMapListInteger.forEach(System.out::println); //flatMapListAnimal 一对多映射 初始Animal数组 名称一个拼接~~~,一个拼接!!! //需要Animal 实现Cloneable接口 List<Animal> flatMapListAnimal = animalList.stream().flatMap(x -> { List<Animal> animals = new ArrayList<>(); Animal clone = x.clone(); x.setName(x.getName() + "~~~"); clone.setName(clone.getName() + "!!!"); animals.add(x); animals.add(clone); return animals.stream(); }).collect(Collectors.toList()); System.out.println("一对多映射 初始Animal数组 名称一个拼接~~~,一个拼接!!!"); flatMapListAnimal.forEach(System.out::println);
Animal类修改
@Override public Animal clone() { Animal animal = null; try { animal = (Animal) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return animal; }
输出结果:
一对多映射 初始Integer数组 一个+10,一个-10: 14 -6 13 -7 17 -3 19 -1 18 -2 12 -8 11 -9 一对多映射 初始Animal数组 名称一个拼接~~~,一个拼接!!! {name='皮皮~~~~~~', type='狗', age=5} {name='皮皮~~~!!!', type='狗', age=5} {name='犇犇~~~~~~', type='狗', age=1} {name='犇犇~~~!!!', type='狗', age=1} {name='小六~~~~~~', type='狗', age=2} {name='小六~~~!!!', type='狗', age=2} {name='咪咪~~~~~~', type='猫', age=3} {name='咪咪~~~!!!', type='猫', age=3} {name='胖虎~~~~~~', type='猫', age=10} {name='胖虎~~~!!!', type='猫', age=10} {name='来福~~~~~~', type='猫', age=2} {name='来福~~~!!!', type='猫', age=2}
5 归约 reduce
//reduce 求和方式1 Optional<Integer> sum1 = list.stream().reduce((x, y) -> x + y); //reduce 求和方式2 Optional<Integer> sum2 = list.stream().reduce(Integer::sum); //reduce 求和方式3 Integer sum3 = list.stream().reduce(0, Integer::sum); System.out.println("reduce 求和方式1:" + sum1.get()); System.out.println("reduce 求和方式2:" + sum2.get()); System.out.println("reduce 求和方式3:" + sum3);
输出结果:
reduce 求和方式1:34 reduce 求和方式2:34 reduce 求和方式3:34
6 收集 collect
6.1 归集 toList/toSet/toMap
//collect 归集 toList/toSet/toMap List<Integer> collectList = list.stream() .filter(item -> item < 8) .collect(Collectors.toList()); Set<Integer> collectSet = list.stream() .filter(item -> item < 8) .collect(Collectors.toSet()); Map<Integer, Integer> collectMap = list.stream() .filter(item -> item < 8) .collect(Collectors.toMap(item -> item, item -> item)); System.out.println("collect 归集toList:" + collectList); System.out.println("collect 归集toSet:" + collectSet); System.out.println("collect 归集toMap:" + collectMap);
输出结果:
collect 归集toList:[4, 3, 7, 2, 1] collect 归集toSet:[1, 2, 3, 4, 7] collect 归集toMap:{1=1, 2=2, 3=3, 4=4, 7=7}
注:如果map中有重复的key,会报错
Exception in thread "main" java.lang.IllegalStateException: Duplicate key 1 at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133) at java.util.HashMap.merge(HashMap.java:1254) at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320) at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499) at com.zhow.Stream_04_Test.main(Stream_04_Test.java:33)
6.2 统计 count/averaging
// 求总数 Long count = list.stream().collect(Collectors.counting()); // 求平均 Double average = list.stream().collect(Collectors.averagingDouble(Integer::doubleValue)); // 求最高 Optional<Integer> max = list.stream().collect(Collectors.maxBy(Integer::compare)); // 求和 Integer sum = list.stream().collect(Collectors.summingInt(Integer::intValue)); // 一次性统计所有信息 DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(Integer::intValue)); System.out.println("总数:" + count); System.out.println("平均:" + average); System.out.println("最高:" + max); System.out.println("总和:" + sum); System.out.println("所有统计:" + collect);
输出结果:
总数:7 平均:4.857142857142857 最高:Optional[9] 总和:34 所有统计:DoubleSummaryStatistics{count=7, sum=34.000000, min=1.000000, average=4.857143, max=9.000000}
6.3 分组 partitioningBy/groupingBy
//分组 partitioningBy/groupingBy // 按动物年龄大于4分组 Map<Boolean, List<Animal>> age = animalList.stream().collect(Collectors.partitioningBy(x -> x.getAge() > 4)); // 按动物类别分组 Map<String, List<Animal>> type = animalList.stream().collect(Collectors.groupingBy(Animal::getType)); // 将员工先按性别分组,再按地区分组 Map<String, Map<Boolean, List<Animal>>> ageType = animalList.stream().collect(Collectors.groupingBy(Animal::getType, Collectors.groupingBy(x -> x.getAge() > 4))); System.out.println("按动物年龄大于4分组:" + age); System.out.println("按动物类别分组:" + type); System.out.println("按动物按类别、年龄:" + ageType);
结果输出:
按动物年龄大于4分组:{false=[{name='犇犇', type='狗', age=1}, {name='小六', type='狗', age=2}, {name='咪咪', type='猫', age=3}, {name='来福', type='猫', age=2}], true=[{name='皮皮', type='狗', age=5}, {name='胖虎', type='猫', age=10}]} 按动物类别分组:{狗=[{name='皮皮', type='狗', age=5}, {name='犇犇', type='狗', age=1}, {name='小六', type='狗', age=2}], 猫=[{name='咪咪', type='猫', age=3}, {name='胖虎', type='猫', age=10}, {name='来福', type='猫', age=2}]} 按动物按类别、年龄:{狗={false=[{name='犇犇', type='狗', age=1}, {name='小六', type='狗', age=2}], true=[{name='皮皮', type='狗', age=5}]}, 猫={false=[{name='咪咪', type='猫', age=3}, {name='来福', type='猫', age=2}], true=[{name='胖虎', type='猫', age=10}]}}
6.4 拼接 joining
//拼接 joining //所有宠物名称拼接 String nameString = animalList.stream().map(Animal::getName).collect(Collectors.joining(",")); System.out.println("所有宠物名称拼接:" + nameString);
结果输出:
所有宠物名称拼接:皮皮,犇犇,小六,咪咪,胖虎,来福
6.5 归约 reducing
//归约 reducing //宠物年龄总和 Optional<Integer> age2 = animalList.stream().map(Animal::getAge).collect(Collectors.reducing(Integer::sum)); System.out.println("宠物年龄总和:" + age2.get());
结果输出:
宠物年龄总和:23
7 排序 sorted
//7、排序 //自然排序 流中元素需实现Comparable接口 Stream<Animal> sorted1 = animalList.stream().sorted(); //按名字排序 Stream<Animal> sorted2 = animalList.stream().sorted(Comparator.comparing(Animal::getName)); //先按年龄再按名字排序 Stream<Animal> sorted3 = animalList.stream().sorted(Comparator.comparing(Animal::getAge).thenComparing(Animal::getName)); //自定义 先按年龄再按名字排序 Stream<Animal> sorted4 = animalList.stream().sorted((x, y) -> { if (x.getAge() == y.getAge()) { return x.getName().compareTo(y.getName()); } else { return x.getAge() - y.getAge(); } }); System.out.println("自然排序:"); sorted1.forEach(System.out::print); System.out.println(); System.out.println("按名字排序:"); sorted2.forEach(System.out::print); System.out.println(); System.out.println("先按年龄再按名字排序:"); sorted3.forEach(System.out::print); System.out.println(); System.out.println("自定义 先按年龄再按名字排序:"); sorted4.forEach(System.out::print); System.out.println();
结果输出:
自然排序: {name='犇犇', type='狗', age=1}{name='小六', type='狗', age=2}{name='来福', type='猫', age=2}{name='咪咪', type='猫', age=3}{name='皮皮', type='狗', age=5}{name='胖虎', type='猫', age=10} 按名字排序: {name='咪咪', type='猫', age=3}{name='小六', type='狗', age=2}{name='来福', type='猫', age=2}{name='犇犇', type='狗', age=1}{name='皮皮', type='狗', age=5}{name='胖虎', type='猫', age=10} 先按年龄再按名字排序: {name='犇犇', type='狗', age=1}{name='小六', type='狗', age=2}{name='来福', type='猫', age=2}{name='咪咪', type='猫', age=3}{name='皮皮', type='狗', age=5}{name='胖虎', type='猫', age=10} 自定义 先按年龄再按名字排序: {name='犇犇', type='狗', age=1}{name='小六', type='狗', age=2}{name='来福', type='猫', age=2}{name='咪咪', type='猫', age=3}{name='皮皮', type='狗', age=5}{name='胖虎', type='猫', age=10}
8 提取/组合
//提取/组合 //concat:合并两个流 Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4); Stream<Integer> integerStream2 = Stream.of(5, 6, 7, 8); List<Integer> concatList = Stream.concat(integerStream1, integerStream2).collect(Collectors.toList()); System.out.println("concat:合并两个流:" + concatList); //distinct:去重 list = Arrays.asList(4, 3, 7, 9, 8, 2, 1, 3, 4); List<Integer> distinctList = list.stream().distinct().collect(Collectors.toList()); System.out.println("去重:" + distinctList); //limit:限制从流中获得前n个数据 List<Integer> limitList = list.stream().limit(5).collect(Collectors.toList()); System.out.println("限制从流中获得前5个数据:" + limitList); //skip:跳过前n个数据 List<Integer> skipList = list.stream().skip(5).collect(Collectors.toList()); System.out.println("跳过前5个数据:" + skipList);
结果输出:
concat:合并两个流:[1, 2, 3, 4, 5, 6, 7, 8] 去重:[4, 3, 7, 9, 8, 2, 1] 限制从流中获得前5个数据:[4, 3, 7, 9, 8] 跳过前5个数据:[2, 1, 3, 4]
这篇关于Java8 Stream(三):StreamAPI的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-28MQ底层原理资料详解:新手入门教程
- 2024-11-28MQ项目开发资料详解:新手入门教程
- 2024-11-28MQ项目开发资料详解:入门与初级用户指南
- 2024-11-28MQ消息队列资料入门教程
- 2024-11-28MQ消息队列资料:新手入门详解
- 2024-11-28MQ消息中间件资料详解与应用教程
- 2024-11-28MQ消息中间件资料入门教程
- 2024-11-28MQ源码资料详解与入门教程
- 2024-11-28MQ源码资料入门教程
- 2024-11-28RocketMQ底层原理资料详解