java stream中Collectors的用法

简介: java stream中Collectors的用法

目录



java stream中Collectors的用法


简介


在java stream中,我们通常需要将处理后的stream转换成集合类,这个时候就需要用到stream.collect方法。collect方法需要传入一个Collector类型,要实现Collector还是很麻烦的,需要实现好几个接口。


于是java提供了更简单的Collectors工具类来方便我们构建Collector。


下面我们将会具体讲解Collectors的用法。


假如我们有这样两个list:


List<String> list = Arrays.asList("jack", "bob", "alice", "mark");
List<String> duplicateList = Arrays.asList("jack", "jack", "alice", "mark");


上面一个是无重复的list,一个是带重复数据的list。接下来的例子我们会用上面的两个list来讲解Collectors的用法。


Collectors.toList()


List<String> listResult = list.stream().collect(Collectors.toList());
        log.info("{}",listResult);


将stream转换为list。这里转换的list是ArrayList,如果想要转换成特定的list,需要使用toCollection方法。


Collectors.toSet()


Set<String> setResult = list.stream().collect(Collectors.toSet());
        log.info("{}",setResult);


toSet将Stream转换成为set。这里转换的是HashSet。如果需要特别指定set,那么需要使用toCollection方法。


因为set中是没有重复的元素,如果我们使用duplicateList来转换的话,会发现最终结果中只有一个jack。


Set<String> duplicateSetResult = duplicateList.stream().collect(Collectors.toSet());
        log.info("{}",duplicateSetResult);


Collectors.toCollection()


上面的toMap,toSet转换出来的都是特定的类型,如果我们需要自定义,则可以使用toCollection()


List<String> custListResult = list.stream().collect(Collectors.toCollection(LinkedList::new));
        log.info("{}",custListResult);


上面的例子,我们转换成了LinkedList。


Collectors.toMap()


toMap接收两个参数,第一个参数是keyMapper,第二个参数是valueMapper:


Map<String, Integer> mapResult = list.stream()
                .collect(Collectors.toMap(Function.identity(), String::length));
        log.info("{}",mapResult);


如果stream中有重复的值,则转换会报IllegalStateException异常:


Map<String, Integer> duplicateMapResult = duplicateList.stream()
                .collect(Collectors.toMap(Function.identity(), String::length));


怎么解决这个问题呢?我们可以这样:


Map<String, Integer> duplicateMapResult2 = duplicateList.stream()
                .collect(Collectors.toMap(Function.identity(), String::length, (item, identicalItem) -> item));
        log.info("{}",duplicateMapResult2);


在toMap中添加第三个参数mergeFunction,来解决冲突的问题。


Collectors.collectingAndThen()


collectingAndThen允许我们对生成的集合再做一次操作。


List<String> collectAndThenResult = list.stream()
                .collect(Collectors.collectingAndThen(Collectors.toList(), l -> {return new ArrayList<>(l);}));
        log.info("{}",collectAndThenResult);


Collectors.joining()


Joining用来连接stream中的元素:


String joinResult = list.stream().collect(Collectors.joining());
        log.info("{}",joinResult);
        String joinResult1 = list.stream().collect(Collectors.joining(" "));
        log.info("{}",joinResult1);
        String joinResult2 = list.stream().collect(Collectors.joining(" ", "prefix","suffix"));
        log.info("{}",joinResult2);


可以不带参数,也可以带一个参数,也可以带三个参数,根据我们的需要进行选择。


Collectors.counting()


counting主要用来统计stream中元素的个数:


Long countResult = list.stream().collect(Collectors.counting());
        log.info("{}",countResult);


Collectors.summarizingDouble/Long/Int()


SummarizingDouble/Long/Int为stream中的元素生成了统计信息,返回的结果是一个统计类:


IntSummaryStatistics intResult = list.stream()
                .collect(Collectors.summarizingInt(String::length));
        log.info("{}",intResult);


输出结果:


22:22:35.238 [main] INFO com.flydean.CollectorUsage - IntSummaryStatistics{count=4, sum=16, min=3, average=4.000000, max=5}


Collectors.averagingDouble/Long/Int()


averagingDouble/Long/Int()对stream中的元素做平均:


Double averageResult = list.stream().collect(Collectors.averagingInt(String::length));
        log.info("{}",averageResult);


Collectors.summingDouble/Long/Int()


summingDouble/Long/Int()对stream中的元素做sum操作:


Double summingResult = list.stream().collect(Collectors.summingDouble(String::length));
        log.info("{}",summingResult);


Collectors.maxBy()/minBy()


maxBy()/minBy()根据提供的Comparator,返回stream中的最大或者最小值:


Optional<String> maxByResult = list.stream().collect(Collectors.maxBy(Comparator.naturalOrder()));
        log.info("{}",maxByResult);


Collectors.groupingBy()


GroupingBy根据某些属性进行分组,并返回一个Map:


Map<Integer, Set<String>> groupByResult = list.stream()
                .collect(Collectors.groupingBy(String::length, Collectors.toSet()));
        log.info("{}",groupByResult);


Collectors.partitioningBy()


PartitioningBy是一个特别的groupingBy,PartitioningBy返回一个Map,这个Map是以boolean值为key,从而将stream分成两部分,一部分是匹配PartitioningBy条件的,一部分是不满足条件的:


Map<Boolean, List<String>> partitionResult = list.stream()
                .collect(Collectors.partitioningBy(s -> s.length() > 3));
        log.info("{}",partitionResult);


看下运行结果:


22:39:37.082 [main] INFO com.flydean.CollectorUsage - {false=[bob], true=[jack, alice, mark]}

结果被分成了两部分。


总结


Collectors是一个非常强大的工具类,希望大家能够灵活使用。


本文的例子https://github.com/ddean2009/learn-java-streams/tree/master/Collectors

相关文章
|
9天前
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
1月前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
56 6
|
1月前
|
Java API 开发者
Java中的Lambda表达式与Stream API的协同作用
在本文中,我们将探讨Java 8引入的Lambda表达式和Stream API如何改变我们处理集合和数组的方式。Lambda表达式提供了一种简洁的方法来表达代码块,而Stream API则允许我们对数据流进行高级操作,如过滤、映射和归约。通过结合使用这两种技术,我们可以以声明式的方式编写更简洁、更易于理解和维护的代码。本文将介绍Lambda表达式和Stream API的基本概念,并通过示例展示它们在实际项目中的应用。
|
23天前
|
Rust 安全 Java
Java Stream 使用指南
本文介绍了Java中Stream流的使用方法,包括如何创建Stream流、中间操作(如map、filter、sorted等)和终结操作(如collect、forEach等)。此外,还讲解了并行流的概念及其可能带来的线程安全问题,并给出了示例代码。
|
2月前
|
安全 Java API
Java中的Lambda表达式与Stream API的高效结合####
探索Java编程中Lambda表达式与Stream API如何携手并进,提升数据处理效率,实现代码简洁性与功能性的双重飞跃。 ####
28 0
|
3月前
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
50 1
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
3月前
|
Java Shell 流计算
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
28 1
Flink-02 Flink Java 3分钟上手 Stream SingleOutputStreamOpe ExecutionEnvironment DataSet FlatMapFunction
|
2月前
|
Java API 数据处理
探索Java中的Lambda表达式与Stream API
【10月更文挑战第22天】 在Java编程中,Lambda表达式和Stream API是两个强大的功能,它们极大地简化了代码的编写和提高了开发效率。本文将深入探讨这两个概念的基本用法、优势以及在实际项目中的应用案例,帮助读者更好地理解和运用这些现代Java特性。
|
3月前
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。
144 3
|
4月前
|
存储 Java API
Java——Stream流详解
Stream流是JDK 8引入的概念,用于高效处理集合或数组数据。其API支持声明式编程,操作分为中间操作和终端操作。中间操作包括过滤、映射、排序等,可链式调用;终端操作则完成数据处理,如遍历、收集等。Stream流简化了集合与数组的操作,提升了代码的简洁性
194 11