java新特性--03-1--Stream---Collectors工具类

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


1.stream 收集

在这里插入图片描述

Collectors工具类

在这里插入图片描述
在这里插入图片描述

注意区分 Collections工具类

在这里插入图片描述

练习1:查找工资大于6000的员工,结果返回为一个List

   @Test
    public 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

 @Test
    public 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 ;c

    int  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,值类型为:ArrayList
        Map<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;
        }

        @Override
        public 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());

    }

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值