前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java Sream中自定义Collector实现复杂数据收集方法

Java Sream中自定义Collector实现复杂数据收集方法

作者头像
公众号:码到三十五
发布2024-08-22 15:30:54
510
发布2024-08-22 15:30:54
举报
文章被收录于专栏:设计模式

Java Stream API中的Collector接口是一个强大的工具,它允许我们自定义数据收集、转换和聚合的过程。

1. Collector接口的作用

Collector接口定义了数据收集、转换和聚合的基本操作,使得从Stream中收集到特定的数据结构或执行复杂的聚合操作成为可能。Collector接口为Stream操作提供了一个终止方法,将Stream的处理结果收集到一个特定的容器中。

2. Collector接口的组成

Collector接口包含以下五个主要方法:

  1. supplier():返回一个新的结果容器的Supplier。这个方法用于创建用于存储收集结果的容器。
  2. accumulator():接收一个结果容器和一个流中的元素,将元素添加到结果容器中。这是累积元素的核心方法,用于将流中的元素逐个添加到结果容器中。
  3. combiner():接收两个结果容器,合并它们。在并行流处理中,如果有多个结果容器被生成,则使用combiner()方法将它们合并为一个容器。
  4. finisher():接收一个结果容器,返回最终结果。这个方法通常用于将结果容器转换为最终想要的形式,例如,对容器中的元素进行排序或过滤。
  5. characteristics():返回一个不可变的Set,包含收集器的特性。这些特性用于优化流处理过程,如并行流处理或结果的无序性。
3. Collector接口的工作原理

Collector接口的工作原理基于上述五个方法的协作。先通过supplier()方法创建一个新的结果容器。然后,遍历Stream中的每个元素,使用accumulator()方法将元素添加到结果容器中。在并行流处理中,如果有多个结果容器被生成,则使用combiner()方法将它们合并为一个容器。最后,通过finisher()方法将结果容器转换为最终想要的形式,并返回。

4. Collector的预定义实现Collectors

Collectors可以看做是Collector接口的实现工厂,提供了多个用于数据收集、转换和聚合的预定义收集器,如toList()、toSet()、toMap()、joining()、counting()、summingInt()、averagingInt()等。这些收集器利用Collector接口实现,使得从Stream中收集数据变得更为方便和高效。

代码语言:javascript
复制
List<String> list = Stream.of("a", "b", "c")
.collect(Collectors.toList());

Map<Character, List<String>> grouped = Stream.of("a", "b", "c")
.collect(Collectors.groupingBy(s -> s.charAt(0)));

String joined = Stream.of("a", "b", "c")
.collect(Collectors.joining(", "));

如,toList()收集器通过调用new ArrayList<>()来创建一个新的结果容器,并使用accumulator()方法将流中的元素添加到结果容器中。toMap()收集器则创建一个新的HashMap,并使用提供的键函数和值函数将元素映射到Map的键和值上。

5. 自定义Collector的使用场景

通过实现Collector接口来自定义复杂的收集器,以满足特定的数据处理需求。自定义Collector时,要实现上述五个方法,并定义如何收集、转换和聚合数据。

如,自定义CollectorPerson对象进行排序,并根据特定条件进行分组:

代码语言:javascript
复制
public static class CustomCollector<T> implements Collector<Person, List<Person>, Map<String, List<Person>>> {
    @Override
    public Supplier<List<Person>> supplier() {
        return ArrayList::new;
    }

    @Override
    public BiConsumer<List<Person>, Person> accumulator() {
        return (list, person) -> list.add(person);
    }

    @Override
    public BinaryOperator<List<Person>> combiner() {
        return (list1, list2) -> {
            list1.addAll(list2);
            return list1;
        };
    }

    @Override
    public Function<List<Person>, Map<String, List<Person>>> finisher() {
        return list -> {
            Map<String, List<Person>> result = new HashMap<>();
            // 自定义排序规则
            list.sort((p1, p2) -> {
                if (p1.age != null && p2.age != null) {
                    return p1.age.compareTo(p2.age);
                } else if (p1.age != null) {
                    return -1;
                } else if (p2.age != null) {
                    return 1;
                } else {
                    return p1.name.compareTo(p2.name);
                }
            });

            // 自定义分组规则
            for (Person person : list) {
                if (result.containsKey(person.name.substring(0, 2))) {
                    result.get(person.name.substring(0, 2)).add(person);
                } else {
                    List<Person> group = new ArrayList<>();
                    group.add(person);
                    result.put(person.name.substring(0, 2), group);
                }
            }
            return result;
        };
    }

    @Override
    public Set<Collector.Characteristics> characteristics() {
        return EnumSet.of(Collector.Characteristics.IDENTITY_FINISH);
    }
}

自定义收集、转换和聚合Person对象的逻辑。使用自定义的排序和分组规则,根据姓名和年龄将Person对象分组并排序,最终返回Map<String, List<Person>>。 通过自定义Collector,创建特定的收集器,而满足复杂的数据处理需求。

使用方法:

代码语言:javascript
复制
import java.util.*;
public class CustomCollectorDemo {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 23),
                new Person("Charlie", 28),
                new Person("David", 25),
                new Person("Eva", 23),
                new Person("Frank", 28)
        );
        Map<String, List<Person>> result = people.stream()
                .collect(new CustomCollector<>());
        System.out.println(result);
    }

    static class Person {
        String name;
        Integer age;
        ...
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. Collector接口的作用
  • 2. Collector接口的组成
  • 3. Collector接口的工作原理
  • 4. Collector的预定义实现Collectors
  • 5. 自定义Collector的使用场景
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档