栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

return new CollectorImpl(

StringBuilder::new, StringBuilder::append,

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

StringBuilder::toString, CH_NOID);

}

  • Supplier< A> supplier()

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

  • BiConsumer accumulator

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

  • BinaryOperator< A> combiner

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

  • Function finisher

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

  • Set< Characteristics> characteristics

无任何行为。

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

2.2 joining(CharSequence delimiter)

public static Collector joining(CharSequence delimiter) {

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

}

public static Collector 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 accumulator

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

  • BinaryOperator< A> combiner

组合器,StringJoiner::merge。

  • Function finisher

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

  • Set< Characteristics> characteristics

无任何行为。

其示例如下:

3、聚合相关收集器


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

public static Collector minBy(Comparator comparator)

public static Collector maxBy(Comparator comparator)

public static Collector summingInt(ToIntFunction mapper)

public static Collector summingLong(ToLongFunction mapper)

public static Collector summingDouble(ToDoubleFunction mapper)

public static Collector averagingInt(ToIntFunction mapper)

public static Collector averagingLong(ToLongFunction mapper)

public static Collector averagingDouble(ToDoubleFunction mapper)

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

4 分组


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

4.1 从示例入手

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

public static Collector> groupingBy(

Function classifier)

  • Collector>>

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

  • Function 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 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>类型的数据。

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

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

  • T : ShopCar

  • K : String (sellerName的类型)

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

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

public static void test_group_jdk8(List shopCars) {

Map shopBySellerNameMap =

shopCars

.stream()

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

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

print(shopBySellerNameMap);

}

其运行效果如下:

为了加深对groupingBy方法的理解,接下来我们重点分析一下其源码的实现。

4.2 源码分析groupingBy方法

public static Collector> groupingBy(Function classifier) { // @1

return groupingBy(classifier, toList()); // @2

}

代码@1:分类参数,已经在上文中详细介绍。

代码@2:调用groupingBy重载方法,传入的参数为toList(),有点意思,传入的参数为Collectors.toList(),结合上文中的示例,需要返回值类型为:Map>,与这里的List对应起来了。

public static Collector> groupingBy(Function classifier, Collector downstream) {

return groupingBy(classifier, HashMap::new, downstream);

}

该重载方法,再次调用3个参数的groupingBy方法,其中第二个参数为HashMap::new,即创建一个Map对象,我们重点关注3个参数的groupingBy。

public static > Collector groupingBy(

Function classifier,

Supplier mapFactory,

Collector downstream) { // @1

Supplier downstreamSupplier = downstream.supplier(); // @2 start

BiConsumer downstreamAccumulator = downstream.accumulator();

BiConsumer, T> accumulator = (m, t) -> {

K key = Objects.requireNonNull(classifier.apply(t), “element cannot be mapped to a null key”);

A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());

downstreamAccumulator.accept(container, t);

}; // @2 end

BinaryOperator> merger = Collectors.>mapMerger(downstream.combiner()); // @3

@SuppressWarnings(“unchecked”)

Supplier> mangledFactory = (Supplier>) mapFa

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

ctory;

if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { // @4

return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);

}

else { // @5

@SuppressWarnings(“unchecked”)

Function downstreamFinisher = (Function) downstream.finisher();

Function, M> finisher = intermediate -> {

intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));

@SuppressWarnings(“unchecked”)

M castResult = (M) intermediate;

return castResult;

};

return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);

}

}

代码@1:参数介绍:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/439914.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号