且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JDK 1.8 使用Stream实现List操作小结

更新时间:2022-06-07 06:11:27

1,首先,有一个普通的DTO对象

public class Employee {


/**
 * 姓名
 */
private String name;

/**
 * 性别
 */
private String gender;

/**
 * 薪资
 */
private Double salary;

public Employee(String name, String gender, double salary) {
    super();
    this.name = name;
    this.gender = gender;
    this.salary = salary;
}
@Override
public String toString() {
    return "Employee [name=" + name + ", gender=" + gender + ", salary=" + salary + "]";
}

public Employee() {
    super();
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public Double getSalary() {
    return salary;
}

public void setSalary(Double salary) {
    this.salary = salary;
}

public String getGender() {
    return gender;
}

public void setGender(String gender) {
    this.gender = gender;
}


}


2,对集合实现各种操作和运算结果

public class MainClass {


public static void main(String arg[]) {
    List<Employee> list = new ArrayList<Employee>();
    list.add(new Employee("宋江","男",1500));
    list.add(new Employee("武松","男",1200));
    list.add(new Employee("林冲","男",1000));
    list.add(new Employee("扈三娘","女",800));
    list.add(new Employee("顾大嫂","女",500));
    
    // 筛选符合某条件的元素 -> 求性别为男的员工集合
    List<Employee> l1 = list.stream().filter(e -> e.getGender().equals("男")).collect(Collectors.toList());
    // 结果 -> [Employee [name=宋江, gender=男, salary=1500.0], Employee [name=武松, gender=男, salary=1200.0], Employee [name=林冲, gender=男, salary=1000.0]]

    
    // 获取集合中的某一元素的集合 ->获取所有员工的姓名集合
    List<String> l2 = list.stream().map(Employee::getName).collect(Collectors.toList());
    // 结果 -> [宋江, 武松, 林冲, 扈三娘, 顾大嫂]

    
    // 分组函数groupingBy 按性别进行分组统计人数
    Map<String, Integer> map = list.stream().collect(Collectors.groupingBy(Employee::getGender, Collectors.summingInt(p -> 1)));
    // 结果 -> {女=2, 男=3}

    
    // 集合中某元素的求和 -> 求性别为男的员工总岁数
    Double sum = list.stream().filter(e -> e.getGender().equals("男")).mapToDouble(Employee::getSalary).sum();
    // 结果 -> 3700.0

    
    //归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出
    //求薪资最高的员工
    Employee em = list.stream().reduce((e1, e2) -> e1.getSalary() > e2.getSalary() ? e1:e2).get();
    // 或者直接用Collectors.maxBy 方法
    Employee e2 = list.stream().collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary))).get();
    // 结果 -> Employee [name=宋江, gender=男, salary=1500.0]

    
    // 匹配元素
    // anyMatch 是否匹配任一元素,查看元素中是否有工资小于600的
    boolean check1 = list.stream().anyMatch(e -> e.getSalary() < 600); // 结果 -> true

    // allMatch 是否匹配所有元素 查看是否所有员工的工资都小于600
    boolean check2 = list.stream().allMatch(e -> e.getSalary() < 600); // 结果 -> false

    // noneMatch 是否未匹配所有元素 查看是否所有员工工资都大于400 
    boolean check3 = list.stream().noneMatch(e -> e.getSalary() < 400);// 结果 -> true

    
    
    // 求元素的平均值 -> 员工的平均工资
    // 求所有人的平均工资
    double avg = list.stream().collect(Collectors.averagingDouble(Employee::getSalary));
    // 结果 -> 1000.0

    
    //按薪资从小到大排序
    List<Employee> l3 = list.stream().sorted((s1, s2) -> s1.getSalary().compareTo(s2.getSalary())).collect(Collectors.toList());
    // 结果 -> [Employee [name=顾大嫂, gender=女, salary=500.0], Employee [name=扈三娘, gender=女, salary=800.0], Employee [name=林冲, gender=男, salary=1000.0], 
    //        Employee [name=武松, gender=男, salary=1200.0], Employee [name=宋江, gender=男, salary=1500.0]]

    
  // 截取 -> 求薪资最少的两个员工,在上述 l3的结果上截取
  List<Employee> l4 = l3.stream().limit(2).collect(Collectors.toList());
  // 结果-> [Employee [name=顾大嫂, gender=女, salary=500.0], Employee [name=扈三娘, gender=女, salary=800.0]]

  
  // 获取所有的名字,组成一条语句 参数分别为(CharSequence delimiter,CharSequence prefix,CharSequence suffix)
  String str = list.stream().map(Employee::getName).collect(Collectors.joining(",", "[", "]"));
  // 结果->[宋江,武松,林冲,扈三娘,顾大嫂]

  
  //用于收集统计数据(如计数,最小值,最大值,总和和平均值)的状态对象
  // 获取工资的最大值、最小值、平均值、求和等等
  DoubleSummaryStatistics doubleSummaryStatistics = list.stream().mapToDouble(Employee::getSalary).summaryStatistics();
  double average = doubleSummaryStatistics.getAverage(); // 结果 -> 1000.00
  double max = doubleSummaryStatistics.getMax();         // 结果 -> 1500.0
  double min = doubleSummaryStatistics.getMin();         // 结果 -> 500.00
  long count = doubleSummaryStatistics.getCount();       // 结果 -> 5
  double sum2 = doubleSummaryStatistics.getSum();        // 结果 -> 5000.00

  
  
  // list转换成map 某两个元素作为键值对
  // 员工的姓名最为key, 薪资作为value 转化成map
  Map<String, Double> map1 = list.stream().collect(Collectors.toMap(Employee::getName, Employee::getSalary));
  // 结果 -> {武松=1200.0, 林冲=1000.0, 扈三娘=800.0, 顾大嫂=500.0, 宋江=1500.0}
  
  // 返回对象本身
  Map<String, Employee> map2 = list.stream().collect(Collectors.toMap(Employee::getName, employee->employee));
  // 结果 -> {武松=Employee [name=武松, gender=男, salary=1200.0], 林冲=Employee [name=林冲, gender=男, salary=1000.0], 扈三娘=Employee [name=扈三娘, gender=女, salary=800.0],
  //        顾大嫂=Employee [name=顾大嫂, gender=女, salary=500.0], 宋江=Employee [name=宋江, gender=男, salary=1500.0]}

  
  //在list转为map时,作为key的值有可能重复,这时候流的处理会抛出个异常:Java.lang.IllegalStateException:Duplicate key。
  //这时候就要在toMap方法中指定当key冲突时key的选择。(这里是选择第二个key覆盖第一个key)
  Map<String, Employee> map3 = list.stream().collect(Collectors.toMap(Employee::getName,Function.identity(),(k1,k2)->k2));
  
  // 返回的value 是集合
  // 员工的性别为key,对象集合为value
  Map<String, List<Employee>> map4 = list.stream().collect(Collectors.groupingBy(Employee::getGender));
  // 结果 -> {女=[Employee [name=扈三娘, gender=女, salary=800.0], Employee [name=顾大嫂, gender=女, salary=500.0]], 
  //          男=[Employee [name=宋江, gender=男, salary=1500.0], Employee [name=武松, gender=男, salary=1200.0], Employee [name=林冲, gender=男, salary=1000.0]]}

  
  // 利用skip 和limit 实现分页需求  list.stream().skip(pageSize * (pageNum - 1)).limit(pageSize).collect(Collectors.toList());
  // 查询第一页的信息, pageSize =10 pageNum =1
  List<Employee> l5 = list.stream().skip(0).limit(10).collect(Collectors.toList());
  // 结果-> [Employee [name=宋江, gender=男, salary=1500.0], Employee [name=武松, gender=男, salary=1200.0], Employee [name=林冲, gender=男, salary=1000.0], 
  //         Employee [name=扈三娘, gender=女, salary=800.0], Employee [name=顾大嫂, gender=女, salary=500.0]]
 
  
}

}