Java 8 stream 流 拆分list

背景:希望List  可以根据某个字段 进行分组 然后拆分

使用Java 8 的流来做。

java.util.stream.Collectors#groupingBy(java.util.function.Function<? super T,? extends K>, java.util.stream.Collector<? super T,A,D>)

使用Group By 方法 默认会转换为 List

可以看到 默认是使用toList()

classifer 是返回的Map的Key 。

groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}

public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
这个可以提供转换的downStream,变成希望的类型。
public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream)
好了 来几个例子吧:
TestPerson 类, List 存储的是这个对象
private static class TestPerson {

        String userName;
        int id;
        int age;

        public TestPerson(String userName, int id, int age) {
            this.userName = userName;
            this.id = id;
            this.age = age;
        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public int getAge() {
            return age;
        }

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

        @Override
        public String toString() {
            return "TestPerson{" +
                    "userName='" + userName + '\'' +
                    ", id=" + id +
                    ", age=" + age +
                    '}';
        }
    }
}

List 中 存储一些对象

List<TestPerson> persons = Arrays.asList(
new TestPerson("zhangsan",1,20),
new TestPerson("lisi",2,21),
new TestPerson("wangwu",3,20)
);

案例1 :根据Age 分组,并且拆分成两个group
Map<Integer, List<TestPerson>> personPerAge = persons.stream().collect(groupingBy(TestPerson::getAge));
System.out.println("分成了"+personPerAge.size()+"组");
for(List<TestPerson> personList : personPerAge.values()) {
System.out.println("One group:");
for(TestPerson person :personList){
System.out.println(person);
}
}

console:

分成了 2组
One group:
TestPerson{userName='zhangsan', id=1, age=20}
TestPerson{userName='wangwu', id=3, age=20}
One group:
TestPerson{userName='lisi', id=2, age=21}

案例2 :   根据一个对象进行分组,

假设每个人都有个班级或者等级吧 , 这个时候我希望 同时加上这个班级的名称 进行分组

private static class TestClass{
        private TestPerson person;
        private String className;

        public TestPerson getPerson() {
            return person;
        }

        public void setPerson(TestPerson person) {
            this.person = person;
        }

        public String getClassName() {
            return className;
        }

        public void setClassName(String className) {
            this.className = className;
        }
    }

 案例3 可以拿到每组中的最大值,平均值,最小值等等 ,是不是和数据库很像?

 public static void main(String[] args) {
        TestPerson zhangsan = new TestPerson("zhangsan",1,18);
        TestPerson lisi = new TestPerson("lisi", 1, 19);
        TestPerson wangwu = new TestPerson("wangwu", 2, 20);
        TestPerson wangwu1 = new TestPerson("wangwu1", 2, 21);
        /*List<TestClass> classes = Arrays.asList(
                new TestClass(zhangsan,"A"),
                new TestClass(zhangsan,"B"),
                new TestClass(wangwu,"C")
                );

        Map<TestPerson, List<TestClass>> classPerPerson = classes.stream().collect(groupingBy(TestClass :: getPerson));
        System.out.println("分成了"+classPerPerson.size()+"组");
        for(List<TestClass> classList : classPerPerson.values()) {
            System.out.println("One group:");
            for(TestClass clazz : classList){
                System.out.println(clazz);
            }
        }*/
        List<TestPerson> persons = Arrays.asList(
                zhangsan,
                lisi,
                wangwu,
                wangwu1
        );
        Map<Integer, IntSummaryStatistics> personPerAge = persons.stream().collect(groupingBy(TestPerson::getId, summarizingInt(TestPerson::getAge)));
        personPerAge.forEach((k,v) ->
                System.out.println("This group id is "+k+" and the summary is " +v)
        );
    }

对 后面我使用了forEach 和Lamda 表达式 一起配合使用, 

当然 还支持过滤功能 ,大家可以一起来玩哈。

参考文章:

https://www.baeldung.com/java-groupingby-collector

https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/index.html

posted on 2019-01-03 16:14  哆啦任意门  阅读(20720)  评论(0编辑  收藏  举报

导航