深入理解 Java 8 Stream 之 collect()

Java 8 引入了 Stream API,提供了一种高效且易于使用的数据处理方式。collect() 方法是 Stream API 中一个非常强大的工具,用于将流中的元素收集到集合或其他容器中。本文将详细介绍 collect() 方法的基础用法及各种高阶用法。

基础用法

collect() 方法的基本形式如下:

<R> R collect(Collector<? super T, A, R> collector);

其中:

  • T 是流中元素的类型。
  • R 是最终结果的类型。
  • A 是累加器的类型,用于中间计算。

最常见的 Collector 实现是 Collectors 类提供的静态方法。下面是一些基础用法的例子。

1. 收集到列表
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> upperCaseNames = names.stream()
                                  .map(String::toUpperCase)
                                  .collect(Collectors.toList());
System.out.println(upperCaseNames); // 输出: [ALICE, BOB, CHARLIE]
2. 收集到集合
Set<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5).stream()
                            .filter(n -> n % 2 == 0)
                            .collect(Collectors.toSet());
System.out.println(numbers); // 输出: [2, 4]
3. 收集到字符串
String result = Arrays.asList("a", "b", "c").stream()
                     .collect(Collectors.joining(", "));
System.out.println(result); // 输出: a, b, c
高阶用法
1. 分组

groupingBy 方法可以将流中的元素按某个属性分组。

List<Person> people = Arrays.asList(
    new Person("Alice", 25),
    new Person("Bob", 30),
    new Person("Charlie", 25)
);

Map<Integer, List<Person>> peopleByAge = people.stream()
                                              .collect(Collectors.groupingBy(Person::getAge));
System.out.println(peopleByAge);
// 输出: {25=[Person{name='Alice', age=25}, Person{name='Charlie', age=25}], 30=[Person{name='Bob', age=30}]}
2. 多级分组

可以使用嵌套的 groupingBy 进行多级分组。

Map<Integer, Map<String, List<Person>>> peopleByAgeAndCity = people.stream()
                                                                 .collect(Collectors.groupingBy(Person::getAge, 
                                                                                               Collectors.groupingBy(Person::getCity)));
System.out.println(peopleByAgeAndCity);
// 输出: {25={New York=[Person{name='Alice', age=25, city='New York'}], Los Angeles=[Person{name='Charlie', age=25, city='Los Angeles'}]}, 30={Chicago=[Person{name='Bob', age=30, city='Chicago'}]}}
3. 分区

partitioningBy 方法可以将流中的元素按布尔条件分成两个部分。

Map<Boolean, List<Person>> adults = people.stream()
                                         .collect(Collectors.partitioningBy(p -> p.getAge() >= 18));
System.out.println(adults);
// 输出: {false=[], true=[Person{name='Alice', age=25}, Person{name='Bob', age=30}, Person{name='Charlie', age=25}]}
4. 自定义收集器

可以使用 Collector.of 方法创建自定义的收集器。

class Person {
    private String name;
    private int age;

    // 构造函数、getter 和 setter 省略

    public static Collector<Person, ?, Integer> totalAge() {
        return Collector.of(
            () -> 0, // 初始化累加器
            (sum, person) -> sum + person.getAge(), // 累加函数
            (sum1, sum2) -> sum1 + sum2, // 合并函数
            sum -> sum // 结果函数
        );
    }
}

int totalAge = people.stream()
                     .collect(Person::totalAge);
System.out.println(totalAge); // 输出: 80
5. 统计信息

Collectors 类提供了多种统计信息的收集器,如 summarizingIntsummarizingLongsummarizingDouble

IntSummaryStatistics stats = people.stream()
                                  .collect(Collectors.summarizingInt(Person::getAge));
System.out.println(stats); // 输出: IntSummaryStatistics{count=3, sum=80, min=25, average=26.666667, max=30}
总结

collect() 方法是 Java 8 Stream API 中一个非常强大且灵活的工具,它可以用于将流中的元素收集到各种集合中,进行分组、分区、统计等操作。通过 Collectors 类提供的丰富方法,可以轻松实现复杂的数据处理任务。希望本文能帮助你更好地理解和使用 collect() 方法。

如果你有任何问题或需要进一步的解释,请随时提问!

相关推荐
GoodStudyAndDayDayUp9 分钟前
IDEA能够从mapper跳转到xml的插件
xml·java·intellij-idea
装不满的克莱因瓶39 分钟前
【Redis经典面试题六】Redis的持久化机制是怎样的?
java·数据库·redis·持久化·aof·rdb
n北斗1 小时前
常用类晨考day15
java
骇客野人1 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
yuanbenshidiaos2 小时前
c++---------数据类型
java·jvm·c++
向宇it2 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
Lojarro2 小时前
【Spring】Spring框架之-AOP
java·mysql·spring
莫名其妙小饼干2 小时前
网上球鞋竞拍系统|Java|SSM|VUE| 前后端分离
java·开发语言·maven·mssql
isolusion2 小时前
Springboot的创建方式
java·spring boot·后端
zjw_rp3 小时前
Spring-AOP
java·后端·spring·spring-aop