提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 1.stream 收集
- Collectors工具类
- 注意区分 Collections工具类
- 练习1:查找工资大于6000的员工,结果返回为一个List
- 练习2:查找年龄小于40的员工,结果返回为一个set
- 练习2:Collectors.toMap
- (v1, v2) -> v2
- 2.Collectors.groupingBy
- 1. 基础分组功能 (3种写法一样效果)
- 2.自定义键——字段映射![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9b6cc419aa2e49ba8e30b0986b30562b.png)
- 3.自定义键——范围
- 4.计数 求和 平均值
- 3.Function.identity()
- 1.JDK源码
- 2.用法
- 不适用场景
- 3.案例
- 案例1
- 案例2
- 对比 Collectors.groupingBy
1.stream 收集
Collectors工具类
注意区分 Collections工具类
练习1:查找工资大于6000的员工,结果返回为一个List
@Testpublic void test02() {List<Employee> list = new ArrayList<>();list.add(new Employee(1001, "马化腾", 34, 6000.38));list.add(new Employee(1002, "马云", 12, 9876.12));list.add(new Employee(1003, "刘强东", 33, 3000.82));list.add(new Employee(1004, "雷军", 26, 7657.37));list.add(new Employee(1005, "李彦宏", 65, 5555.32));list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));list.add(new Employee(1007, "任正非", 26, 4333.32));list.add(new Employee(1008, "扎克伯格", 35, 2500.32));List<Employee> employeeList = list.stream().filter(e ->e.getSalary() > 6000).collect(Collectors.toList());employeeList.forEach(System.out::println);}
练习2:查找年龄小于40的员工,结果返回为一个set
@Testpublic void test02() {List<Employee> list = new ArrayList<>();list.add(new Employee(1001, "马化腾", 34, 6000.38));list.add(new Employee(1002, "马云", 12, 9876.12));list.add(new Employee(1003, "刘强东", 33, 3000.82));list.add(new Employee(1004, "雷军", 26, 7657.37));list.add(new Employee(1005, "李彦宏", 65, 5555.32));list.add(new Employee(1006, "比尔盖茨", 42, 9500.43));list.add(new Employee(1007, "任正非", 26, 4333.32));list.add(new Employee(1008, "扎克伯格", 35, 2500.32));Set<Employee> employeeSet = list.stream().filter(employee ->employee.getAge() < 40).collect(Collectors.toSet());employeeSet.forEach(System.out::println);}
练习2:Collectors.toMap
package com.cy.month11;import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;public class Test05 {public static void main(String[] args) {List<Employee> list = Arrays.asList(new Employee("1","张三"),new Employee("2","李四"),new Employee("3","王五"));Map<String, String> map = list.stream().collect(Collectors.toMap(Employee::getId, Employee::getName));System.out.println(map.toString());}private static class Employee {String id;String name;public Employee(String id, String name) {this.id = id;this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
}
(v1, v2) -> v2
- (v1, v2) -> v2 表示如果有相同的key,则使用后面的值覆盖key已经有的值。
- 如果(v1, v2) ->v1, 则不覆盖,保留key已经有的值。
Map相同的key只能有一个。(注意:如果不指定覆盖策略,遇到相同key会抛异常)
案例
public static void main(String[] args) {List<Person> personList =new ArrayList<>();personList.add(new Person("于问问","988"));personList.add(new Person("苗问问","988"));personList.add(new Person("李问问","777"));Map<String, String> personMap = personList.stream().collect(Collectors.toMap(Person::getCode, Person::getName));}
这样会不会有问题?答案是会有问题的。
Map的key值不能重复,现在于问问和苗问问的code号都是988
遇到这种情况转Map时就必须得有取舍了,苗问问和于问问只能留一个,那就留苗问问吧
Map<String, String> personMap = personList.stream().collect(Collectors.toMap(Person::getCode, Person::getName, (v1, v2) -> v2));
2.Collectors.groupingBy
@Data
@AllArgsConstructor
public class Student {String name ;int age;String clazz ;String course ;cint score;}
1. 基础分组功能 (3种写法一样效果)
- 说明:基础功能,分组并返回Map容器。将用户自定义的元素作为键,同时将键相同的元素存放在List中作为值。
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class test {public static void main(String[] args) {List<Student> students = Stream.of(new Student("张三", 16, "高一1班", "语文", 88),new Student("李四", 17, "高一2班", "数学", 90),new Student("王五", 18, "高一3班", "外语", 100)).collect(Collectors.toList());// 方法1 :将不同课程的学生进行分类Map<String, List<Student>> groupByCourse = students.stream().collect(Collectors.groupingBy(Student::getCourse));System.out.println(groupByCourse);// 方法2 :上面的方法中容器类型和值类型都是默认指定的,容器类型为:HashMap,值类型为:ArrayListMap<String, List<Student>> groupByCourse1 = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.toList()));System.out.println(groupByCourse1);// 方法3 : 可以通过下面的方法自定义返回结果、值的类型Map<String, List<Student>> groupByCourse2 = students.stream().collect(Collectors.groupingBy(Student::getCourse, HashMap::new, Collectors.toList()));System.out.println(groupByCourse2);}}
{数学=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=90)], 语文=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=88)], 外语=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}
{数学=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=90)], 语文=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=88)], 外语=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}
{数学=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=90)], 语文=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=88)], 外语=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}
2.自定义键——字段映射
package com.cy.demo;import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class test {public static void main(String[] args) {List<Student> students = Stream.of(new Student("张三", 16, "高一1班", "语文", 88),new Student("李四", 17, "高一2班", "数学", 90),new Student("王五", 18, "高一3班", "外语", 100)).collect(Collectors.toList());// 字段映射 分组显示每个课程的学生信息Map<String, List<Student>> filedKey = students.stream().collect(Collectors.groupingBy(Student::getCourse));System.out.println(filedKey);// 组合字段 分组现实每个班不同课程的学生信息Map<String, List<Student>> combineFiledKey = students.stream().collect(Collectors.groupingBy(student -> student.getClazz() + "#" + student.getCourse()));System.out.println(combineFiledKey);}}
{数学=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=90)],
语文=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=88)],
外语=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}{高一2班#数学=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=90)],高一1班#语文=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=88)], 高一3班#外语=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}
3.自定义键——范围
package com.cy.demo;import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class test {public static void main(String[] args) {List<Student> students = Stream.of(new Student("张三", 16, "高一1班", "语文", 75),new Student("李四", 17, "高一2班", "数学", 55),new Student("王五", 18, "高一3班", "外语", 100)).collect(Collectors.toList());// 根据两级范围 将学生划分及格不及格两类Map<Boolean, List<Student>> customRangeKey = students.stream().collect(Collectors.groupingBy(student -> student.getScore() > 60));System.out.println(customRangeKey);// 根据多级范围 根据学生成绩来评分Map<String, List<Student>> customMultiRangeKey = students.stream().collect(Collectors.groupingBy(student -> {if (student.getScore() < 60) {return "C";} else if (student.getScore() < 80) {return "B";}return "A";}));System.out.println(customMultiRangeKey);}}
{false=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=55)],true=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=75), Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)]}{A=[Student(name=王五, age=18, clazz=高一3班, course=外语, score=100)],
B=[Student(name=张三, age=16, clazz=高一1班, course=语文, score=75)],
C=[Student(name=李四, age=17, clazz=高一2班, course=数学, score=55)]}
4.计数 求和 平均值
package com.cy.demo;import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class test {public static void main(String[] args) {List<Student> students = Stream.of(new Student("张三", 16, "高一1班", "语文", 75),new Student("李四", 17, "高一2班", "数学", 55),new Student("王五", 18, "高一3班", "外语", 100),new Student("赵六", 18, "高一1班", "语文", 88)).collect(Collectors.toList());// 计数Map<String, Long> groupCount = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.counting()));System.out.println(groupCount);// 求和Map<String, Integer> groupSum = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.summingInt(Student::getScore)));System.out.println(groupSum);// 增加平均值计算Map<String, Double> groupAverage = students.stream().collect(Collectors.groupingBy(Student::getCourse, Collectors.averagingInt(Student::getScore)));System.out.println(groupAverage);}}
3.Function.identity()
1.JDK源码
Java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法,identity()就是Function接口的一个静态方法。
- Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t形式的Lambda表达式。
2.用法
当我们使用 Stream 想要将集合的某一属性(例如手机号)作为 key,对象本身作为 value 时,就可以在 Collectors.toMap() 中配合使用 Function.identity()。
// 查询数据
List<UserInfo> list = userInfoMapper.getList();
// 获取 手机号-UserInfo 映射
Map<String, UserInfo> phoneNumberMap = list.stream().collect(Collectors.toMap(UserInfo::getPhoneNumber(), Function.identity(), (v1, v2) -> v1));
不适用场景
不适用于 mapToInt()、mapToLong()、mapToDouble() 等需要进行拆箱操作的场景。
public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 2, 3);int[] array = list.stream().mapToInt(Function.identity()).toArray();System.out.println(array.length);
}
3.案例
案例1
public static void main(String[] args) {Stream<String> stream = Stream.of("This", "is", "a", "test");Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length));System.out.println(map);}
案例2
private static class Employee {String id;String age;String name;public Employee(String id, String age, String name) {this.id = id;this.name = name;this.age = age;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}@Overridepublic String toString() {return "Employee{" +"id='" + id + '\'' +", age='" + age + '\'' +", name='" + name + '\'' +'}';}}
public static void main(String[] args) {List<Employee> list = Arrays.asList(new Employee("1","18","张三"),new Employee("2","25","李四"),new Employee("3","25","王五"));Map<String, String> map1 = list.stream().collect(Collectors.toMap(Employee::getId, Employee::getName,(v1, v2) -> v2) );System.out.println(map1.toString());Map<String, Employee> map2 = list.stream().collect(Collectors.toMap(Employee::getId, Function.identity()));System.out.println(map2.toString());}
对比 Collectors.groupingBy
- Function.identity() 返回是对象本身 Map<String, Employee>
- Collectors.groupingBy 返回的是 Map<String, List< Employee>>
public static void main(String[] args) {List<Employee> list = Arrays.asList(new Employee("1","18","张三"),new Employee("2","25","李四"),new Employee("3","25","王五"));Map<String, String> map1 = list.stream().collect(Collectors.toMap(Employee::getId, Employee::getName,(v1, v2) -> v2) );System.out.println(map1.toString());Map<String, Employee> map2 = list.stream().collect(Collectors.toMap(Employee::getId, Function.identity()));System.out.println(map2.toString());Map<String, List<Employee>> map3 = list.stream().collect(Collectors.groupingBy(Employee::getId));System.out.println(map3.toString());Map<String, List<Employee>> map4 = list.stream().collect(Collectors.groupingBy(Employee::getAge));System.out.println(map4.toString());}