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

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

相关推荐
程序猿小D6 分钟前
第三百三十一节 Java网络教程 - Java网络UDP多播
java·网络·udp
灭掉c与java9 分钟前
第五章springboot实现web的常用功能
java·spring boot·spring
初晴~20 分钟前
【Spring】RESTful设计风格
java·后端·spring·springboot·restful
风动也无爱39 分钟前
Java的正则表达式和爬虫
java·爬虫·正则表达式
訴山海40 分钟前
解决Excel文件流读取数字为时间乱码问题
java·文件流
今日之风甚是温和1 小时前
【Excel】拆分多个sheet,为单一表格
java·excel·sheet·vb宏
聂 可 以1 小时前
IDEA一键启动多个微服务
java·微服务·intellij-idea
刘大浪1 小时前
IDEA 2024安装指南(含安装包以及使用说明 cannot collect jvm options 问题一)
java·ide·intellij-idea
菠菠萝宝1 小时前
【YOLOv8】安卓端部署-1-项目介绍
android·java·c++·yolo·目标检测·目标跟踪·kotlin
CoderJia程序员甲2 小时前
重学SpringBoot3-如何发送 Email
java·spring boot·后端·email