java grouping,介绍 Java 8 groupingBy Collector

java grouping,介绍 Java 8 groupingBy Collector介绍Java8groupingByCollector本文我们探讨下Java8groupingByCollector,通过不同的示例进行详细讲解。GroupingByCollectorJava8StreamAPI提供了声明方式处理流数据。static工厂方法Collectors.groupingBy()和Collectors.groupingByConcurrent()…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

介绍 Java 8 groupingBy Collector

本文我们探讨下Java 8 groupingBy Collector,通过不同的示例进行详细讲解。

GroupingBy Collector

Java 8 Stream API 提供了声明方式处理流数据。static工厂方法Collectors.groupingBy() 和 Collectors.groupingByConcurrent() 实现类似SQL语句的“Group By”字句功能,实现根据一些属性进行分组并把结果存在Map实例。

重载groupingBy的几个方法:

static Collector>>

groupingBy(Function super T,? extends K> classifier)

提供后续收集器参数:

static Collector>

groupingBy(Function super T,? extends K> classifier,

Collector super T,A,D> downstream)

提供map 提供者和后续收集器参数:

static > Collector

groupingBy(Function super T,? extends K> classifier,

Supplier mapFactory, Collector super T,A,D> downstream)

下面通过示例详细看看每个方法的应用场景。

基础准备

为了演示groupingBy(),让我们定义BlogPost类(作为流使用):

class BlogPost {

String title;

String author;

BlogPostType type;

int likes;

}

BlogPostType:

enum BlogPostType {

NEWS,

REVIEW,

GUIDE

}

定义一个BlogPost列表:

List posts = Arrays.asList( … );

同时也订一个Tuple类用于根据多个属性进行分组:

class Tuple {

BlogPostType type;

String author;

}

通过单个属性简单分组

首先从最简单的groupingBy 方法开始,使用一个分类函数作为参数。分类函数应用于流中的每个元素。函数的返回值用于map的key,映射至分组集合。根据post类型进行分组的代码:

Map> postsPerType = posts.stream()

.collect(groupingBy(BlogPost::getType));

根据复杂类型进行分组

Map> postsPerTypeAndAuthor = posts.stream()

.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));

分组类型不限于标量或字符串类型。map的key可以是任何对象类型,只有我们确保实现必要的equals 和 hashcode 方法。下面根据组合类型进行分组:

Map> postsPerTypeAndAuthor = posts.stream()

.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));

修改返回Map值类型

第二个重载groupingBy方法带另一个参数指定后续收集器,应用于第一个集合结果。当我们仅指定一个分类器函数,没有后续收集器,则返回toList()集合。如何后续收集器使用toSet(),则会获得Set集合,而不是List:

Map> postsPerType = posts.stream()

.collect(groupingBy(BlogPost::getType, toSet()));

根据多个字段进行分组

与应用后续收集器不同的是,可以指定第二个分类器对第一个分组结果再分组。对BlogPost类的List根据作者和类型进行分组代码如下:

Map> map = posts.stream()

.collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));

获取分组结果的平均值

通过使用后续收集器可以对分组函数的结果使用聚集函数。获取每种blog类型的平均数:

Map averageLikesPerType = posts.stream()

.collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));

获取分组结果之和

计算每个分组之和:

Map likesPerType = posts.stream()

.collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));

获取分组结果的最大值和最小值

另外可以通过聚集函数获取最大数量的blog类型:

Map> maxLikesPerPostType = posts.stream()

.collect(groupingBy(BlogPost::getType,

maxBy(comparingInt(BlogPost::getLikes))));

类似的,我们能应用minBy后续收集器获得最小数量的分类。注意,maxBy和minBy 收集器考虑到应用它的集合可能是空的。这就是为什么map中的值类型是可选的。

获取属性分组结果的摘要信息

Collectors API提供了摘要收集器,用于需要同时获取数值属性的count,sum, minimum, maximum ,average 值。下面计算每种类型的摘要信息:

Map likeStatisticsPerType = posts.stream()

.collect(groupingBy(BlogPost::getType,

summarizingInt(BlogPost::getLikes)));

每个类型的IntSummaryStatistics 对象包括属性的 count, sum, average, min 和 max值。另外摘要对象也有double和long类型。

映射分组结果至不同类型

更复杂的聚集可以对分类结果应用后续映射收集器。下面获得每个类型的连接blog的标题。

Map postsPerType = posts.stream()

.collect(groupingBy(BlogPost::getType,

mapping(BlogPost::getTitle, joining(“, “, “Post titles: [“, “]”))));

上面代码实现映射每个BlogPost 实例至title,然后reduce 文章标题流至连接字符串。本例Map的值是字符串,而不是默认List类型。

修改返回 Map 类型

当使用groupingBy 收集器,我们不能确定返回Map的类型。如果我们想指定特定Map类型作为返回值,我们使用三个参数的groupingBy 方法,通过提供Map supplier函数,其允许我们改变Map的类型。

通过EnumMap supplier函数给goupingBy方法获取EnumMap:

EnumMap> postsPerType = posts.stream()

.collect(groupingBy(BlogPost::getType,

() -> new EnumMap<>(BlogPostType.class), toList()));

并发Grouping By Collector

类似于 groupingBy, 也有groupingByConcurrent 收集器,其利用多线程架构。其有三个重载方法,带有与groupingBy一样的参数。然而,groupingByConcurrent 收集器的返回值必须是ConcurrentHashMap 类或其子类。

实现并发分组的代码如下:

ConcurrentMap> postsPerType = posts.parallelStream()

.collect(groupingByConcurrent(BlogPost::getType));

如果你选择传递Map supplier函数给groupingByConcurrent 收集器,那么需要确保函数返回值也必须是ConcurrentHashMap 类或其子类。

总结

本文我们看了Java 8 中提供的几个groupingBy collector示例。groupingBy可以对流元素根据其属性进行分组,然后进一步收集、改变并收集至最终的容器中。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/171310.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • iframe自适应高度和宽度[通俗易懂]

    iframe自适应高度和宽度[通俗易懂]iframe自适应高度和宽度可以通过onload事件来操作,如:functioniframLoad(ifm){ try{ $(ifm).height(ifm.contentWindow.document.body.scrollHeight); $(ifm).width(ifm.cont

    2022年10月12日
  • 基尼系数近似计算:sql (hive)实现 简单高效

    基尼系数近似计算:sql (hive)实现 简单高效通过近似的方法,如何在sql中计算基尼系数。如何在python中实现基尼系数计算的两种方法,可以查看我的另一篇文章。两篇文章取数相同,可以结合去看。如果想加深对基尼系数计算的逻辑:可查看文章http://www.cnblogs.com/longwind09/p/8047539.html。本文中采用的近似方法,如何建立近似计算公式、如何简化推导公式可查看文章,本文基于这篇文章进行注…

    2022年10月10日
  • python button使用方法_python gui界面设计

    python button使用方法_python gui界面设计Button控件是一种标准Tkinter控件,用来展现不同样式的按钮.Button控件被用以和用户交互,比如按钮被鼠标点击后,某种操作被启动.和Label控件类似,按钮可以展示图片或者文字.不同的是,Label控件可以指定字体,Button控件只能使用单一的字体.Button上的文字可以多行显示.可以将一个Python函数或方法绑定到一个B

    2022年8月30日
  • 从零和使用mxnet实现softmax分类

    1.softmax从零实现(1797,64)(1797,)(1797,10)epoch:50,loss:[1.9941667],accuracy:0.3550361713967724

    2021年12月30日
  • matlab怎么fprintf,matlab中的fprintf函数怎么用「建议收藏」

    matlab怎么fprintf,matlab中的fprintf函数怎么用「建议收藏」matlab中的fprintf函数怎么用发布时间:2020-06-2217:10:46来源:亿速云阅读:97作者:Leahmatlab中的fprintf函数怎么用?针对这个问题,今天小编总结了这篇文章,希望能帮助更多想解决这个问题的朋友找到更加简单易行的办法。fprintf函数可以将数据按指定格式写入到文本文件中。其调用格式为:数据的格式化输出:fprintf(fid,format,vari…

    2022年8月31日
  • python json转对象

    python json转对象json转对象是python比较常见的一个应用场景,如何来实现呢?这里会涉及json模块中的loads方法,具体操作如下:导入json包importjson自定义classclassResult:def__init__(self,token,userName,empCode):self.token=tokenself.userName=userNameself.empCode=empCode添加需转换j

    2022年10月26日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号