java8实战:使用流收集数据之toList、joining、groupBy(多字段分组)(1)

最后

这份《“java高分面试指南”-25分类227页1000+题50w+字解析》同样可分享给有需要的朋友,感兴趣的伙伴们可挑战一下自我,在不看答案解析的情况,测试测试自己的解题水平,这样也能达到事半功倍的效果!(好东西要大家一起看才香)

image

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

本文将从Collectos中构建收集器入手,详细介绍java8提供了哪些收集器,重点介绍:toList、toSet、toCollection、joining、groupBy(包含多级分组)、reducing的核心实现原理与使用示例。

本节目录

    • 1、toList、toSet、toCollection
  • 2、joining

    • 2.1 joining
  • 2.2 joining(CharSequence delimiter)

  • 3、聚合相关收集器

  • 4 分组

    • 4.1 从示例入手
  • 4.2 源码分析groupingBy方法

  • 5、 partitioningBy

  • 6、 reducing

1、toList、toSet、toCollection


首先对流中的数据进行计算,最终返回的数据类型为集合。Collectors中定义了如下3集合类收集器,其声明如下:

public static Collector<T, ?, List> toList()

public static Collector<T, ?, Set> toSet()

public static <T, C extends Collection> Collector<T, ?, C> toCollection(Supplier collectionFactory)

温馨提示:建议根据上篇的理论,再来反推一下这些Collector中的核心属性的值,例如supplier、accumulator、combiner、characteristics。不过特别注意,toList、toCollection是不支持并行运行的,但toSet()方法支持并行运行。

我们首先来看一个一直使用的示例,返回菜单中所有菜品的名称:

public static void test_toList(List menu) {

List names = menu.stream().map(Dish::getName)

.collect(Collectors.toList());

}

由于toList方法的实现原理已经在 java8读书笔记:探究java8流收集数据原理中也详细介绍,故本篇不再重点介绍。

2、joining


Collectors定义了如下3个重载方法。

public static Collector<CharSequence, ?, String> joining()

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter)

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,

CharSequence prefix, CharSequence suffix)

2.1 joining

public static Collector<CharSequence, ?, String> joining() {

return new CollectorImpl<CharSequence, StringBuilder, String>(

StringBuilder::new, StringBuilder::append,

(r1, r2) -> { r1.append(r2); return r1; },

StringBuilder::toString, CH_NOID);

}

  • Supplier< A> supplier()

其函数为StringBuilder::new,即通过该方法创建一个StringBuilder方法,作为累积器的初始值。

  • BiConsumer<A, T> accumulator

累积器:StringBuilder::append,即会对流中的元素执行追加。

  • BinaryOperator< A> combiner

组合器,也是调用append方法,进行字符串的规约。

  • Function<A,R> finisher

转换器:由于累积器返回的最终对象为StringBuilder,并不是目标String类型,故需要调用StringBuilder#toString方法进行转换

  • Set< Characteristics> characteristics

无任何行为。

从上面的函数定义我们可以得出该方法的作用:针对字符串流,会对流中的元素执行字符的追加动作,流元素之间没有分隔符号,示例如下:

在这里插入图片描述

2.2 joining(CharSequence delimiter)

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {

return joining(delimiter, “”, “”);

}

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,

CharSequence prefix,

CharSequence suffix) {

return new CollectorImpl<>(

() -> new StringJoiner(delimiter, prefix, suffix),

StringJoiner::add, StringJoiner::merge,

StringJoiner::toString, CH_NOID);

}

  • Supplier< A> supplier()

其函数为() -> new StringJoiner(delimiter, prefix, suffix),累积器的初始值为StringJoiner。

  • BiConsumer<A, T> accumulator

累积器:StringJoiner::append,即会对流中的元素执行追加。

  • BinaryOperator< A> combiner

组合器,StringJoiner::merge。

  • Function<A,R> finisher

转换器:由于累积器返回的最终对象为StringBuilder,并不是目标String类型,故需要调用StringBuilder#toString方法进行转换

  • Set< Characteristics> characteristics

无任何行为。

其示例如下:

在这里插入图片描述

3、聚合相关收集器


聚合相关收集器,主要包括minBy、maxBy、sum、avg等相关函数,其主要方法声明如下:

public static Collector<T, ?, Optional> minBy(Comparator<? super T> comparator)

public static Collector<T, ?, Optional> maxBy(Comparator<? super T> comparator)

public static Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper)

public static Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper)

public static Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper)

public static Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper)

public static Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper)

public static Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper)

上面这些方法比较简单,下面举个简单的例子介绍其使用:

在这里插入图片描述

4 分组


Collectors提供了3个groupingBy重载方法,我们一个一个来理解。

4.1 从示例入手

我们从其中一个最简单的函数说起,从而慢慢引出

public static <T, K> Collector<T, ?, Map<K, List>> groupingBy(

Function<? super T, ? extends K> classifier)

  • Collector<T, ?, Map<K, List< T>>>

首先我们先来关注该方法的返回值Collector<T, ?, Map<K,List< T>>,其最终返回的数据类型为:Map<K, List< T>>

  • Function<? super T, ? extends K> classifier

分类函数。

示例如下:例如如下是购物车实体类,并且初始化数据如下:

public class ShopCar {

private int id;

private int sellerId;

private String sellerName;

private String goodsName;

private int buyerId;

private String buyerName;

private int num;

}

// 初始化数据如下:

public static List initShopCar() {

return Arrays.asList(

new ShopCar(1, 1, “天猫” , “华为手机”, 1 , “dingw”, 5),

new ShopCar(1, 2, “京东” , “华为手机”, 2 , “ly”, 2),

new ShopCar(1, 1, “京东” , “小米手机”, 3 , “zhl”, 3),

new ShopCar(1, 2, “1号店” , “华为手机”, 1 , “dingw”, 5),

new ShopCar(1, 2, “天猫” , “苹果手机”, 1 , “dingw”, 2)

);

}

首先我们看一下java8之前的写法:

public static void test_group_jdk7(List shopCars) {

Map<String, List> shopBySellerNameMap = new HashMap<>();

for(ShopCar c : shopCars ) {

if(shopBySellerNameMap.containsKey( c.getSellerName() )) {

shopBySellerNameMap.get(c.getSellerName()).add©;

} else {

List aList = new ArrayList<>();

shopBySellerNameMap.put(c.getSellerName(), aList);

aList.add©;

}

}

print(shopBySellerNameMap);

}

上面的代码应该很容易理解,根据商家名称进行分组,拥有相同商家的名称的购物车项组成一个集合,最终返回Map<String, List< ShopCar >>类型的数据。

那如何使用java8的流分组特性来编写对应的代码呢?下面的思考过程非常关键,经过前面的学习,我想大家应该也具备了如下分析与编写的能力?

首先其声明如下:public static <T, K> Collector<T, ?, Map<K, List< T>>> groupingBy(Function<? super T, ? extends K> classifier),那在本例中,T,K这两个参数代表什么意思呢?

  • T : ShopCar

  • K : String (sellerName的类型)

其判断的主要依据为groupingBy方法返回的参数Collector<T, ?, Map<K, List< T>>>,代表<T, A, R>,其中最后一个泛型参数R对应的就是本例需要返回的Map<K, List< T>>,故分析出T,K代表的含义。

然后再看其参数:Function<? super T, ? extends K> classifier,即接受的函数式编程接口为T -> K,即通过ShopCar 返回一个String,又根据其名称可知,该函数为一个分类函数,故基本可以写成如下代码:

public static void test_group_jdk8(List shopCars) {

Map<String, List> shopBySellerNameMap =

shopCars

.stream()

.collect(Collectors.groupingBy(ShopCar::getSellerName));

//.collect(Collectors.groupingBy( (ShopCar c) -> c.getSellerName() ))

print(shopBySellerNameMap);

}

其运行效果如下:

在这里插入图片描述为了加深对groupingBy方法的理解,接下来我们重点分析一下其源码的实现。

4.2 源码分析groupingBy方法

Kafka进阶篇知识点

image

Kafka高级篇知识点

image

44个Kafka知识点(基础+进阶+高级)解析如下

image

由于篇幅有限,小编已将上面介绍的**《Kafka源码解析与实战》、Kafka面试专题解析、复习学习必备44个Kafka知识点(基础+进阶+高级)都整理成册,全部都是PDF文档**

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

5XXipz6i-1715289571736)]

Kafka高级篇知识点

[外链图片转存中…(img-1qGhLWrI-1715289571737)]

44个Kafka知识点(基础+进阶+高级)解析如下

[外链图片转存中…(img-FKFNaVO1-1715289571738)]

由于篇幅有限,小编已将上面介绍的**《Kafka源码解析与实战》、Kafka面试专题解析、复习学习必备44个Kafka知识点(基础+进阶+高级)都整理成册,全部都是PDF文档**

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值