java stream group_Java8 Stream之group

1 介绍

2 Collectors的groupingBy方法

使用Java 8 提供的Stream API 可以以声明式的方法来处理集合中的数据。静态工厂方法 Collectors.groupingBy()和Collectors.groupingByConcurrent()提供类似SQL语言中的‘GROUP BY’的功能。两个工厂方法用于根据某些属性对集合中的元素分组并将分组结果存储在Map(ConcurrentMap)中。

groupingBy方法的三个重载版本:

参数为分类函数

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

参数为分类函数、Collector对象(执行reduce操作)

static Collector>

groupingBy(Function super T,? extends K> classifier, Collector super T,A,D> downstream)

参数为分类函数、Supplier对象(提供Map接口的实现,用于分类结果的存储)和Collector对象(执行reduce操作)

static > Collector

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

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

2.1 示例代码设置

文章类型

public enum ArticleType {

NEWS,

REVIEW,

GUIDE

}

文章,包括文章标题、作者、文章类型和文章获得的喜欢数。

public class Article {

String title;

String author;

ArticleType type;

int likes;

}

待处理的文章列表

List articles = Arrays.asList(...);

2.2 基于单属性分组

单属性分组只需要一个分类函数作为参数,分类函数会作用于流的所有元素,分类函数的返回值将作为分组结果的键。

基于作者姓名的分组如下:

Map> byAuthor = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor));

Map> byType = articles.stream()

.collect(Collectors.groupingBy(article -> article.getType()));

2.3 分组结果的键为复杂类型

分类函数不仅限于返回一个纯量或字符串,分类结果的键可以是任何类型,但是要求实现了必要的equals和hashcode方法。

基于作者姓名和文章类型的分组如下:

Map, List> complexKeMap = articles.stream()

.collect(Collectors.groupingBy(new Function>() {

@Override

public Tuple2 apply(Article article) {

return new Tuple2<>(article.getAuthor(), article.getType());

}

}));

2.4 修改分组结果的值类型

默认分组结果的值类型为List,可以通过提供第二个参数来修改返回的类型。返回Set类型的示例代码如下:

// modify the return type Map to Map

Map> authorSet = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.toSet()));

2.5 多条件分组

下面的例子,首先按照作业分组,然后对分组的结果再按照文章类型分组:

Map>> chainGroup = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.groupingBy(Article::getType)));

2.6 对分组结果执行Reduce操作

一般分组结果的值类型为List,可以根据需要对List执行Reduce操作,比如获取List中某个属性值最大最小值的元素。

计算作者文章的获得的喜欢数的平均值:

Map averageLike = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.averagingInt(Article::getLikes)));

计算作者文章得到的喜欢数的总和:

Map sumLike = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.summingInt(Article::getLikes)));

计算每位作者最受欢迎的文章:

Map> maxLikeByAuthor = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.maxBy(Comparator.comparingInt(Article::getLikes))));

System.out.println(maxLikeByAuthor);

计算每位作者最不受欢迎的文章:

Map> minLikeByAuthor = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.minBy(Comparator.comparingInt(Article::getLikes))));

2.7 获取分组结果的统计数据

Stream专门提供了计算分组结果统计值的接口,统计值包括:最大值、最小值、平均值、总数、总和五个指标。

Map summaryStatistics = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.summarizingInt(Article::getLikes)));

2.8 修改分组结果值的类型

Map modifyGroupType = articles.stream()

.collect(Collectors.groupingBy(Article::getAuthor, Collectors.mapping(Article::getTitle, joining("||"))));

System.out.println(modifyGroupType);

2.9 返回支持并发操作的Map

ConcurrentMap> concurrentGroup = articles.parallelStream()

.collect(Collectors.groupingByConcurrent(Article::getAuthor));

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值