List集合中的元素是Person,字段属性如下
@Data
public static class Person {
private String name;
private Integer age;
private Integer score;
private String date;
public Person(String name, Integer age, Integer score, String date) {
this.name = name;
this.age = age;
this.score = score;
this.date = new SimpleDateFormat("yyyy-MM-dd").format(this.birthDay);
}
}
1.List根据对象中某一属性去重
List<Person> arrays = personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
-> new TreeSet<>(Comparator.comparing(Entity :: getName))), ArrayList::new));
2.List分组排序
Map<String, List<Person>> sortedDatas = personList.stream()
//按照getAge倒序排列
.sorted(Comparator.comparing(Person::getAge, Comparator.nullsLast(Comparator.reverseOrder())))
//保证分组后的有序性,容器用LinkedHashMap
.collect(Collectors.groupingBy(Person::getDate, LinkedHashMap::new, Collectors.toList()));
3.List转Map的空值报错问题
Map<String, Integer> nameForAgeMap =
personList.stream().collect(HashMap::new, (m, v) -> m.put(v.getName(), v.getAge()), HashMap::putAll);
4.List实现分页
List<Person> personPageList = personList.stream()
.sorted((o1,o2) -> o2.getAge() - o1.getAge())
.skip((long)(pageNum - 1) * pageSize)
.limit(pageSize).collect(toList())
5.List分组统计功能
前置数据
List<Student> students = Stream.of(
Student.builder().name("小张").age(16).clazz("高一1班").course("历史").score(88).build(),
Student.builder().name("小李").age(16).clazz("高一3班").course("数学").score(12).build(),
Student.builder().name("小王").age(17).clazz("高二1班").course("地理").score(44).build(),
Student.builder().name("小红").age(18).clazz("高二1班").course("物理").score(67).build(),
Student.builder().name("李华").age(15).clazz("高二2班").course("数学").score(99).build(),
Student.builder().name("小潘").age(19).clazz("高三4班").course("英语").score(100).build(),
Student.builder().name("小聂").age(20).clazz("高三4班").course("物理").score(32).build()
).collect(Collectors.toList());
- Collectors.counting:计数
计数语法:
Collector<T, ?, Long> counting()
// 计数
Map<String, Long> groupCount = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.counting()));
- Collectors.summingInt:求和
求和语法:
Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)
Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper)
Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)
// 求和
Map<String, Integer> groupSum = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.summingInt(Student::getScore)));
- Collectors.averagingInt:平均值
平均值语法:
Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)
Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)
Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)
// 增加平均值计算
Map<String, Double> groupAverage = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.averagingInt(Student::getScore)));
- Collectors.minBy:最大最小值
最大最少值语法:
Collector<T, ?, Optional> minBy(Comparator<? super T> comparator)
Collector<T, ?, Optional> maxBy(Comparator<? super T> comparator)
Collectors.collectingAndThen语法:
Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher)
Function<R,RR>:提供参数类型为R,返回结果类型为RR。
// 同组最小值
Map<String, Optional<Student>> groupMin = students.stream()
.collect(Collectors.groupingBy(Student::getCourse,Collectors.minBy(Comparator.comparing(Student::getCourse))));
// 使用Collectors.collectingAndThen方法,处理Optional类型的数据
Map<String, Student> groupMin2 = students.stream()
.collect(Collectors.groupingBy(Student::getCourse,
Collectors.collectingAndThen(Collectors.minBy(Comparator.comparing(Student::getCourse)), op ->op.orElse(null))));
// 同组最大值
Map<String, Optional<Student>> groupMax = students.stream()
.collect(Collectors.groupingBy(Student::getCourse,Collectors.maxBy(Comparator.comparing(Student::getCourse))));
- Collectors.summarizingInt:完整统计(同时获取以上的全部统计结果)
完整统计语法:
Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)
Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)
Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)
// 统计方法同时统计同组的最大值、最小值、计数、求和、平均数信息
HashMap<String, IntSummaryStatistics> groupStat = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, HashMap::new,Collectors.summarizingInt(Student::getScore)));
groupStat.forEach((k, v) -> {
// 返回结果取决于用的哪种计算方式
v.getAverage();
v.getCount();
v.getMax();
v.getMin();
v.getSum();
});
- Collectors.partitioningBy:范围统计
Collectors.partitioningBy语法:
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate)
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream)
- predicate:条件参数,对分组的结果划分为两个范围。
// 切分结果,同时统计大于60和小于60分的人的信息
Map<String, Map<Boolean, List<Student>>> groupPartition = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.partitioningBy(s -> s.getScore() > 60)));
// 同样的,我们还可以对上面两个分组的人数数据进行统计
Map<String, Map<Boolean, Long>> groupPartitionCount = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.partitioningBy(s -> s.getScore() > 60, Collectors.counting())));
Collectors.partitioningBy仅支持将数据划分为两个范围进行统计,如果需要划分多个,可以嵌套Collectors.partitioningBy执行,不过需要在执行完后,手动处理不需要的数据。也可以在第一次Collectors.partitioningBy获取结果后,再分别对该结果进行范围统计。
Map<String, Map<Boolean, Map<Boolean, List<Student>>>> groupAngPartitionCount = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.partitioningBy(s -> s.getScore() > 60,
Collectors.partitioningBy(s -> s.getScore() > 90))));
- Collectors.reducing:合并分组结果
Collectors.reducing语法:
Collector<T, ?, Optional> reducing(BinaryOperator op)
Collector<T, ?, T> reducing(T identity, BinaryOperator op)
Collector<T, ?, U> reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator op)
- identity:合并标识值(因子),它将参与累加函数和合并函数的运算(即提供一个默认值,在流为空时返回该值,当流不为空时,该值作为起始值,参与每一次累加或合并计算)
- mapper:映射流中的某个元素,并根据此元素进行合并。
- op:合并函数,将mapper映射的元素,进行两两合并,最初的一个元素将于合并标识值进行合并。
// 合并结果,计算每科总分
Map<String, Integer> groupCalcSum = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.reducing(0, Student::getScore, Integer::sum)));
// 合并结果,获取每科最高分的学生信息
Map<String, Optional<Student>> groupCourseMax = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(Student::getScore)))));
- Collectors.joining:合并字符串
Collectors.joining语法:
Collector<CharSequence, ?, String> joining()
Collector<CharSequence, ?, String> joining(CharSequence delimiter)
Collector<CharSequence, ?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
- delimiter:分隔符
- prefix:每个字符的前缀
- suffix:每个字符的后缀
Collectors.joining只能对字符进行操作,因此一般会与其它downstream方法组合使用。
// 统计各科的学生姓名
Map<String, String> groupCourseSelectSimpleStudent = students.stream()
.collect(Collectors.groupingBy(Student::getCourse, Collectors.mapping(Student::getName, Collectors.joining(","))));