Java --> 不可变集合+Stream流
1 import java.util.List;
2 import java.util.Map;
3 import java.util.Set;
4
5 public class UnchangeCollectionDemo {
6 //对不可变集合进行增删修改操作时均会抛出异常:UnsupportedOperationException
7 public static void main(String[] args) {
8 //创建List不可变集合
9 List<Double> lists = List.of(436.5,710.2,358.1,524.8);
10 //lists.add(12.2);
11 //lists.set(0,152.4);
12 System.out.println(lists);
13
14 //创建Set不可变集合
15 Set<String> sets = Set.of("Java","C#","HTML");
16 //sets.add("MySQL");
17 System.out.println(sets);
18
19 //创建Map不可变集合
20 Map<String,Integer> maps = Map.of("手表",120,"体恤衫",65,"手机",1850);
21 System.out.println(maps);
22 }
23 }
- 感受Stream流的优点
1 java.util.ArrayList;
2 import java.util.Collections;
3 import java.util.List;
4
5 public class StreamTest {
6 public static void main(String[] args) {
7 List<String> lists = new ArrayList<>();
8 Collections.addAll(lists,"小兵","小强","文天祥","小龙","大兵","干将莫邪","小不点");
9 System.out.println(lists);
10
11 //1、把集合中姓小的放到新集合中
12 List<String> xiaoLists = new ArrayList<>();
13 for (String s : lists) {
14 if (s.startsWith("小")){
15 xiaoLists.add(s);
16 }
17 }
18 System.out.println(xiaoLists);
19
20 //2、把集合中姓名长度为3的放到新集合中
21 List<String> namesThreeLength = new ArrayList<>();
22 for (String s : lists) {
23 if (s.length() == 3){
24 namesThreeLength.add(s);
25 }
26 }
27 System.out.println(namesThreeLength);
28
29 //3、使用Stream实现,支持链式编程
30 lists.stream().filter(s -> s.startsWith("小")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
31 }
示例运行结果:
- 集合、数组获取流的方式:
1 import java.util.*;
2 import java.util.stream.Stream;
3
4 public class StreamDemo2 {
5 public static void main(String[] args) {
6 //Collection集合获取流
7 Collection<String> list = new ArrayList<>();
8 Stream<String> stream = list.stream();
9
10 //Map集合获取流
11 Map<String,Integer> maps = new HashMap<>();
12 //键流
13 Stream<String> keyStream = maps.keySet().stream();
14
15 //值流
16 Stream<Integer> valuesStream = maps.values().stream();
17
18 //键值对流 map 可-> set
19 Stream<Map.Entry<String, Integer>> keyAndValueStream = maps.entrySet().stream();
20
21 //数组获取流
22 String[] names = {"太乙真人","孙悟空","哪吒","雷震子"};
23 Stream<String> namesStream = Arrays.stream(names);
24 Stream<String> nameStream2 = Stream.of(names);
25 }
26 }
Student类
1 public class Student {
2 private String name;
3
4 public Student() {
5 }
6
7 public Student(String name) {
8 this.name = name;
9 }
10
11 public String getName() {
12 return name;
13 }
14
15 public void setName(String name) {
16 this.name = name;
17 }
18
19 @Override
20 public String toString() {
21 return "Student{" +
22 "name='" + name + '\'' +
23 '}';
24 }
25 }
测试类
1 import java.util.ArrayList;
2 import java.util.Collections;
3 import java.util.List;
4 import java.util.stream.Stream;
5
6 public class StreamDemo3 {
7 public static void main(String[] args) {
8 List<String> list = new ArrayList<>();
9 Collections.addAll(list,"后裔","嫦娥","玉兔","张三丰","张昭","张明旺","嫦娥","玉兔","张三丰");
10 // list.stream().filter(new Predicate<String>() {
11 // @Override
12 // public boolean test(String s) {
13 // return s.startsWith("张");
14 // }
15 // });
16
17 System.out.println("-------Lambda表达式简化--------");
18 list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
19
20 System.out.println("--------长度为3的---------");
21 long size = list.stream().filter(s -> s.length() == 3).count();
22 System.out.println(size);
23
24 System.out.println("----------姓张的,只要前两个------------");
25 //list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(s -> System.out.println(s));
26 list.stream().filter(s -> s.startsWith("张")).limit(2).forEach(System.out::println); //条件:两个s一样
27
28 System.out.println("----------跳过前两个姓张的人-----------");
29 list.stream().filter(s -> s.startsWith("张")).skip(2).forEach(System.out::println);
30
31 System.out.println("----Map加工方法,给每个集合前都加上一个”软件学院“-----");
32 // 原数据类型,加工后数据类型
33 // list.stream().map(new Function<String, Object>() {
34 // @Override
35 // public String apply(String s) {
36 // return "软件学院" + s;
37 // }
38 // });
39 list.stream().map( s -> "软件学院" + s).forEach(s -> System.out.println(s));
40
41 System.out.println("--------需求:把所有的名称 都加工成一个学生对象---------");
42 // list.stream().map(new Function<String, Student>() {
43 // @Override
44 // public Student apply(String s) {
45 // return new Student(s);
46 // }
47 // }).forEach(student -> System.out.println(student.getName()));
48
49 //list.stream().map(s -> new Student(s)).forEach(student -> System.out.println(student));
50 list.stream().map(Student::new).forEach(System.out::println); //构造器引用,方法引用
51
52 System.out.println("----合并流------");
53 Stream<String> stream1 = list.stream().filter(s -> s.startsWith("张"));
54 Stream<String> stream2 = Stream.of("Java","MySQL","HTML");
55 //public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
56 System.out.println("----被合并的流(?)必须为合并后的流(T)的子类 [distinct(不同的)->去重复]------");
57 Stream<String> stream3 = Stream.concat(stream1,stream2);
58 stream3.distinct().forEach(s -> System.out.println(s));
59
60 System.out.println("-------通过Stream流对原list集合进行的操作都是返回新的流,并不会对原来的集合造成影响------");
61 list.forEach(s -> System.out.println(s));
62 }
63 }
示例运行结果:
- 案例需求:某个公司的开发部门,分为开发一部和二部,现在需要进行年终的数据结算。
- 分析:
- 员工信息至少包含了(名称、性别、工资、奖金、处罚记录);
- 开发一部有4个员工、开发二部有5个员工;
- 分别筛选出2个部门的最高工资,封装成优秀员工对象Topperformer;
- 分别统计出2个部门的平均月收入,要求去掉最高和最低工资;
- 统计2个部门整体的平均工资,去掉最低和最高工资的平均值
Topperformer类:
1 public class Topperformer {
2 private String name;
3 private double money; //月薪
4
5 public Topperformer() {
6 }
7
8 public Topperformer(String name, double money) {
9 this.name = name;
10 this.money = money;
11 }
12
13 public String getName() {
14 return name;
15 }
16
17 public void setName(String name) {
18 this.name = name;
19 }
20
21 public double getMoney() {
22 return money;
23 }
24
25 public void setMoney(double money) {
26 this.money = money;
27 }
28
29 @Override
30 public String toString() {
31 return "Topperformer{" +
32 "name='" + name + '\'' +
33 ", money=" + money +
34 '}';
35 }
36 }
测试类:
1 import java.math.BigDecimal;
2 import java.math.RoundingMode;
3 import java.util.ArrayList;
4 import java.util.Comparator;
5 import java.util.List;
6 import java.util.function.Consumer;
7 import java.util.function.Function;
8 import java.util.function.Predicate;
9 import java.util.stream.Stream;
10
11 public class StreamDemo4 {
12 public static double allMoney_dep1;
13 public static double allMoney_dep2;
14 public static double allMoney_dep1_dep2;
15 public static long all_members;
16
17 public static void main(String[] args) {
18 List<Employee> department1 = new ArrayList<>();
19 department1.add(new Employee("猪八戒",'男',12000,500,null));
20 department1.add(new Employee("孙悟空",'男',15000,800,"顶撞师傅"));
21 department1.add(new Employee("沙和尚",'男',11000,300,null));
22 department1.add(new Employee("小白龙",'男',13500,500,null));
23
24 List<Employee> department2 = new ArrayList<>();
25 department2.add(new Employee("青狮魔王",'男',18000,500,"被文殊菩萨收服"));
26 department2.add(new Employee("白象魔王",'男',17000,8000,"被普贤菩萨收服"));
27 department2.add(new Employee("大鹏魔王",'男',16000,300,"被如来收服"));
28 department2.add(new Employee("孔雀公主",'女',14500,500,null));
29
30 System.out.println("--------department1部门的最高工资员工----------");
31 // Employee employee = department1.stream().max(new Comparator<Employee>() {
32 // @Override
33 // public int compare(Employee e1, Employee e2) {
34 // return Double.compare(e1.getSalary() + e1.getBonus(),e2.getSalary() + e2.getBonus());
35 // }
36 // }).get();
37 //简化
38 Employee employee = department1.stream().max((e1, e2) ->
39 Double.compare(e1.getSalary() + e1.getBonus(), e2.getSalary() + e1.getBonus())).get();
40 System.out.println(employee);
41 System.out.println("-----1、加工成Topperformer对象------");
42 // Topperformer topperformer = department1.stream().max((e1, e2) ->
43 // Double.compare(e1.getSalary() + e1.getBonus(),
44 // e2.getSalary() + e1.getBonus())).map(new Function<Employee, Topperformer>() {
45 // @Override
46 // public Topperformer apply(Employee employee) {
47 // return new Topperformer(employee.getName(),employee.getSalary() + employee.getBonus());
48 // }
49 // }).get();
50 // System.out.println(topperformer);
51
52 System.out.println("---简化---"); //可被替换为Comparator.comparingDouble(e -> e.getSalary() + e.getBonus())
53 Topperformer topperformer2 = department1.stream().max((e1,e2) -> Double.compare(e1.getSalary()+e1.getBonus(),e2.getSalary()+e2.getBonus())).map(
54 employee1 -> new Topperformer(employee1.getName(),employee1.getSalary()+employee1.getBonus())
55 ).get();
56 System.out.println(topperformer2);
57
58 System.out.println("---2、统计部门1的平均工资,去掉最高工资和最低工资---");
59 //思路:排序员工平均工资,用skip跳过第一个,再用limit(总员工数 - 2)则可以得到剩余所有员工的工资,内部求和后除以总人数减2
60 department1.stream().sorted((e1,e2) -> Double.compare(e1.getSalary() + e1.getBonus(),e2.getSalary() + e2.getBonus()))
61 .skip(1).limit(department1.size() - 2).forEach(new Consumer<Employee>() {
62 @Override
63 public void accept(Employee employee) {
64 allMoney_dep1 += (employee.getBonus()+employee.getSalary());
65 }
66 });
67 System.out.println("department1_avgmoney:" + allMoney_dep1 / (department1.size() - 2) * 1.0);
68
69 System.out.println("---3、统计部门2的平均工资,去掉最高工资和最低工资---");
70 department2.stream().sorted((e1,e2) -> Double.compare(e1.getSalary() + e1.getBonus(),e2.getSalary() + e2.getBonus()))
71 .skip(1).limit(department2.size() - 2).forEach(new Consumer<Employee>() {
72 @Override
73 public void accept(Employee employee) {
74 allMoney_dep2 += (employee.getBonus() + employee.getSalary());
75 }
76 });
77 System.out.println("department_avgmoney:" + allMoney_dep2);
78
79 System.out.println("---4、统计2个开发部门整体的平均工资,去掉最低和最高的平均值---");
80 //思路:合并两个集合流在进行统计
81 Stream<Employee> stream1 = department1.stream();
82 Stream<Employee> stream2 = department2.stream();
83 Stream<Employee> stream_sum = Stream.concat(stream1,stream2);
84
85 all_members = department1.size() + department2.size();
86 stream_sum.sorted((e1,e2) -> Double.compare(e1.getSalary() + e1.getBonus(),e2.getSalary() + e2.getBonus()))
87 .skip(1).limit(all_members - 2).forEach(new Consumer<Employee>() {
88 @Override
89 public void accept(Employee employee) {
90 allMoney_dep1_dep2 += (employee.getSalary() + employee.getBonus());
91 }
92 });
93 //BigDecimal
94 BigDecimal bigDecimal1 = BigDecimal.valueOf(allMoney_dep1_dep2);
95 BigDecimal bigDecimal2 = BigDecimal.valueOf(all_members - 2);
96 //保留两位小数,四舍五入
97 System.out.println("allMoney_dep1_dep2:" + bigDecimal1.divide(bigDecimal2,2, RoundingMode.HALF_UP));
98 }
99 }
示例运行结果:
- Stream流的收集操作:
1 import java.util.*;
2 import java.util.stream.Collectors;
3 import java.util.stream.Stream;
4
5 public class StreamDemo5 {
6 public static void main(String[] args) {
7 List<String> list = new ArrayList<>();
8 Collections.addAll(list,"后裔","嫦娥","玉兔","张三丰","张昭","张明旺","嫦娥","玉兔","张三丰");
9
10 //收集姓张的
11 Stream<String> zhangStream = list.stream().filter(s -> s.startsWith("张"));
12 List<String> zhangList = zhangStream.collect(Collectors.toList());
13 //List<String> zhangList = zhangStream.toList(); jdk16开始,新集合不能被修改
14 System.out.println("List集合:" + zhangList);
15
16 //注意:流只能被操作一次
17 Stream<String> zhangStream2 = list.stream().filter(s -> s.startsWith("张"));
18 Set<String> zhangSet = zhangStream2.collect(Collectors.toSet());
19 System.out.println("Set集合:" + zhangSet);
20
21 //收集成字符数组
22 Stream<String> zhangStream3 = list.stream().filter(s -> s.startsWith("张"));
23 //Object[] zhangArrays = zhangStream3.toArray();
24 String[] zhangArrays = zhangStream3.toArray(String[]::new); //一定要转换成String数组(拓展知识)
25
26 System.out.println("数组:" + Arrays.toString(zhangArrays));
27 }
28 }
示例运行结果: