• Java8 Stream 关于分组、聚合等常用的操作测试


    在平常的业务处理中,总是很喜欢从数据库里查询数List<T>数据,然后自己通过Map遍历去分组,现在发现Stream的分组功能非常好用,在此记录和分享下。
    /**
    * Stream的分组功能测试
    *
    * @author nanfengxiangbei
    * @date 2022-04-13
    */
    public class GroupingByTest {

    /**
    * 对集合按照单个属性分组
    */
    @Test
    public void testGroupingBySingleProperty1() {
    List<String> items = Arrays.asList("apple", "apple", "banana", "apple", "orange", "banana", "papaya");

    // 1、分组,select
    Map<String, List<String>> result1 = items.stream().collect(Collectors.groupingBy(Function.identity()));
    // {papaya=[papaya], orange=[orange], banana=[banana, banana], apple=[apple, apple, apple]}
    System.out.println(result1);


    // 2、分组、计数
    Map<String, Long> result2 = items.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
    // {papaya=1, orange=1, banana=2, apple=3}
    System.out.println(result2);


    // 3、分组、计数、排序
    Map<String, Long> finalMap = new LinkedHashMap<>();
    result2.entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
    .forEachOrdered(e -> finalMap.put(e.getKey(), e.getValue()));
    // {apple=3, banana=2, papaya=1, orange=1}
    System.out.println(finalMap);
    }

    /**
    * 对集合按照单个属性分组
    */
    @Test
    public void testGroupingBySingleProperty2() {
    // select age, List<people> from t_people group by age
    Stream<Person> people = Stream.of(new Person("Paul", 24, 20000),
    new Person("Mark", 30, 30000),
    new Person("Will", 28, 28000),
    new Person("William", 28, 28000));
    Map<Integer, List<Person>> peopleByAge = people.collect(
    Collectors.groupingBy(Person::getAge)
    );
    // {24=[Person{name='Paul', age=24, salary=20000}], 28=[Person{name='Will', age=28, salary=28000}, Person{name='William', age=28, salary=28000}], 30=[Person{name='Mark', age=30, salary=30000}]}
    System.out.println(peopleByAge);

    // select age, count(*) from t_people group by age
    Stream<Person> people2 = Stream.of(new Person("Paul", 24, 20000),
    new Person("Mark", 30, 30000),
    new Person("Will", 28, 28000),
    new Person("William", 28, 28000));
    Map<Integer, Long> peopleByAgeCount = people2.collect(
    Collectors.groupingBy(Person::getAge, Collectors.counting())
    );
    // {24=1, 28=2, 30=1}
    System.out.println(peopleByAgeCount);
    List<Person> list = Arrays.asList(new Person("Paul", 24, 20000),
    new Person("Mark", 30, 30000),
    new Person("Will", 28, 28000),
    new Person("Will", 28, 10000),
    new Person("William", 28, 28000));

    // select name, sum(salary) from t_people group by name
    Map<String, Long> peopleByName = list.stream().collect(
    Collectors.groupingBy(Person::getName, Collectors.summingLong(Person::getSalary))
    );
    // {24=1, 28=2, 30=1}
    System.out.println(peopleByName);

    // select name,List<Person> from t_people group by name
    Map<String, List<Person>> byName = list.stream().collect(
    Collectors.groupingBy(Person::getName)
    );
    System.out.println("根据名称分组:" + byName);

    // select * from t_people t where t.salary>8000
    List<Person> person = list.stream().filter(x -> x.getSalary() > 8000).collect(Collectors.toList());
    System.out.println("高于8000的员工信息:" + person);

    // select t.name from t_people t where t.salary>8000
    List<String> filterList = list.stream()
    .filter(person1 -> person1.getSalary() > 8000)
    .map(Person::getName)
    .collect(Collectors.toList());
    System.out.println("高于8000的员工姓名:" + filterList);

    // select name, max(salary) from t_people group by name
    Optional<Long> max = list.stream().map(Person::getSalary).max(Long::compare);
    System.out.println("max(salary)=" + max);
    Map<String, Person> max2 = list.stream().collect(
    Collectors.toMap(Person::getName, Function.identity(), (c1, c2) -> c1.getSalary() > c2.getSalary() ? c1 : c2)
    );
    System.out.println("max(salary)=" + max2);
    }

    /**
    * 对集合按照多个属性分组
    */
    @Test
    public void testGroupingByMultiProperty() {
    Stream<Person> people = Stream.of(new Person("Paul", 24, 20000),
    new Person("Mark", 30, 30000),
    new Person("Will", 28, 28000),
    new Person("William", 28, 28000));
    Map<String, List<Person>> collect = people.collect(
    Collectors.groupingBy(p -> p.age + "#" + p.salary)
    );
    // {28#28000=[Person{name='Will', age=28, salary=28000}, Person{name='William', age=28, salary=28000}], 30#30000=[Person{name='Mark', age=30, salary=30000}], 24#20000=[Person{name='Paul', age=24, salary=20000}]}
    System.out.println(collect);
    }

    /**
    * 嵌套GroupingBy
    */
    @Test
    public void testNestedGroupingBy() {
    Stream<Person> people = Stream.of(new Person("Paul", 24, 20000),
    new Person("Mark", 30, 30000),
    new Person("Will", 28, 28000),
    new Person("William", 28, 28000));

    Map<String, Map<Integer, List<Person>>> collect = people.collect(
    Collectors.groupingBy(Person::getName, Collectors.groupingBy(Person::getAge))
    );
    System.out.println(collect);
    }

    public static class Person {
    private String name;
    private int age;
    private long salary;

    Person(String name, int age, long salary) {
    this.name = name;
    this.age = age;
    this.salary = salary;
    }

    public String getName() {
    return name;
    }

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

    public int getAge() {
    return age;
    }

    public void setAge(int age) {
    this.age = age;
    }

    public long getSalary() {
    return salary;
    }

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

    @Override
    public String toString() {
    return String.format("Person{name='%s', age=%d, salary=%d}", name, age, salary);
    }
    }
    }
  • 相关阅读:
    Asp.Net开发小技巧汇总
    .net缓存
    C# .Net 2.0实例学习:WebBrowser页面与WinForm交互技巧(二)
    字符和数组
    jvm调优原则
    ASP.NET页面刷新的实现方法
    js禁止右键和复制功能
    动态定义SL DataGrid Columns [转]
    DataGrid 内嵌ComboBox动态数据联动
    C#对象序列化(2)
  • 原文地址:https://www.cnblogs.com/nanfengxiangbei/p/16170868.html
Copyright © 2020-2023  润新知