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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM