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