深入理解 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() 方法。

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

相关推荐
懒鸟一枚12 小时前
深入理解 Linux 内存、Swap 交换分区与分页机制的关系
java·linux·数据库
我命由我1234513 小时前
执行 Gradle 指令报错,无法将“grep”项识别为 cmdlet、函数、脚本文件或可运行程序的名称
android·java·java-ee·android studio·android jetpack·android-studio·android runtime
考虑考虑13 小时前
Sentinel安装
java·后端·微服务
凤凰院凶涛QAQ15 小时前
《Java版数据结构 & 集合类剖析》栈与队列:“push/pop 是栈的灵魂,offer/poll 是队列的骨架——四组 API,两种人生”
java·开发语言·数据结构
掘金_答案16 小时前
上线那天,一个 ConcurrentHashMap 差点送走我的 AI 客服——3 天排查 JVM 血泪史
java·后端·架构
猿与禅16 小时前
CosId 分布式 ID 生成器完全教程:从架构原理到生产落地
java·shardingsphere·雪花算法·分布式id·高性能·cosid·号段模式
MindUp16 小时前
企业网盘权限模型解析:多层级访问控制与审计能力选型指南
java·linux·运维
NG47716 小时前
【软件设计与体系结构】-策略设计模式
java·设计模式·软件工程
程序员天天困17 小时前
优雅记录操作日志:从注解到 SpEL 的全链路实践与开源方案对比
java·后端
战血石LoveYY17 小时前
Integer类型超限,导致数据异常
java·算法