聚合归纳操作

聚合操作一节描述了下列操作管道,计算集合roster中所有男性成员的平均年龄:

double average = roster

.stream()

.filter(p -> p.getGender() == Person.Sex.MALE)

.mapToInt(Person::getAge)

.average()

.getAsDouble();

JDK包含许多终端操作(比如average、sum、min、max和count),它们通过组合流的内容返回一个值,这些操作称为归纳操作。JDK还包含返回一个集合而不是单个值的归纳操作,许多归纳操作执行特定的任务,例如查找值的平均值或将元素分组到类别中。但是,JDK为你提供了通用的reduce和collect操作,本节将详细介绍这些操作。

你可以在示例ReductionExamples中找到本节中描述的代码摘录。

Stream.reduce方法

Stream.reduce方法是一种通用的归纳操作,考虑以下管道,它计算集合roster中男性成员的年龄总和,它使用Stream.sum归纳操作。

Integer totalAge = roster

.stream()

.mapToInt(Person::getAge)

.sum();

将其与下面使用流的管道进行比较,使用Stream.reduce操作计算相同的值:

Integer totalAgeReduce = roster

.stream()

.map(Person::getAge)

.reduce(

0,

(a, b) -> a + b);

本例中的reduce操作有两个参数:

identity:标识元素既是归纳的初始值,也是流中没有元素时的默认结果,在本例中,标示元素为0,这是年龄总和的初始值,如果集合roster中没有成员,则为默认值。

accumulator:累加器函数接受两个参数:归纳的部分结果(在本例中,是到目前为止所有处理过的整数的和)和流的下一个元素(在本例中,是一个整数),它返回一个新的局部结果。在本例中,累加器函数是一个lambda表达式,它添加两个Integer值并返回一个Integer值:(a, b) -> a + b。

reduce操作总是返回一个新值,但是,accumulator函数每次处理流的元素时也会返回一个新值,假设你希望将流的元素归纳为更复杂的对象,例如集合,这可能会影响应用程序的性能。如果reduce操作涉及向集合添加元素,那么每次累加器函数处理一个元素时,它都会创建一个包含该元素的新集合,这是低效的,相反,更新现有的集合将更有效,你可以使用Stream.collect来实现这一点。

Stream.collect方法

与reduce方法不同,collect方法修改或改变现有值,而reduce方法在处理元素时总是创建一个新值。

考虑如何找到流中值的平均值,你需要两段数据:值的总数和这些值的和。然而,与reduce方法和所有其他归纳方法一样,collect方法只返回一个值,你可以创建一个包含成员变量的新数据类型,该成员变量跟踪值的总数和这些值的总和,例如下面的类Averager:

class Averager implements IntConsumer {

private int total = 0;

private int count = 0;

public double average() {

return count > 0 ? ((double) total)/count : 0;

}

public void accept(int i) { total += i; count++; }

public void combine(Averager other) {

total += other.total;

count += other.count;

}

}

下面的管道使用Averager类和collect方法计算所有男性成员的平均年龄:

Averager averageCollect = roster.stream()

.filter(p -> p.getGender() == Person.Sex.MALE)

.map(Person::getAge)

.collect(Averager::new, Averager::accept, Averager::combine);

System.out.println("Average age of male members: " +

averageCollect.average());

本例中的collect操作接受三个参数:

supplier:supplier是个工厂方法,它构造新的实例,对于collect操作,它创建结果容器的实例,在本例中,它是Averager类的一个新实例。

accumulator:accumulator函数将流元素合并到结果容器中,在本例中,它通过将count变量增加1,并将流元素的值添加到total成员变量中,该元素是一个整数,表示男性成员的年龄,来修改Averager结果容器。

combiner:combiner函数接受两个结果容器并合并它们的内容,在本例中,它通过将count变量与另一个Averager实例的count成员变量相加,并将另一个Averager实例的total成员变量的值添加到total成员变量中,从而修改Averager结果容器。

请注意以下:

supplier是lambda表达式(或方法引用),而不是reduce操作中的identity元素之类的值。

accumulator和combiner函数不返回值。

你可以使用并行流的collect操作(如果你使用并行流运行collect方法,那么每当combiner函数创建一个新对象时,JDK都会创建一个新线程,例如本例中的Averager对象,因此,你不必担心同步)。

虽然JDK提供了计算流中元素平均值的average操作,但是如果需要从流的元素中计算多个值,可以使用collect操作和自定义类。

collect操作最适合于集合,下面的示例使用collect操作将男性成员的名称放入集合中:

List namesOfMaleMembersCollect = roster

.stream()

.filter(p -> p.getGender() == Person.Sex.MALE)

.map(p -> p.getName())

.collect(Collectors.toList());

这个版本的collect操作只接受Collector类型的一个参数,该类封装了collect操作中用作参数的函数,该操作需要三个参数(supplier、accumulator和combiner函数)。

Collectors类包含许多有用的归纳操作,比如将元素累积到集合中,并根据各种标准汇总元素,这些归纳操作返回类Collector的实例,因此可以将它们用作collect操作的参数。

本例使用Collectors.toList操作,它将流元素累积到List的新实例中,与Collectors类中的大多数操作一样,toList操作符返回Collector的实例,而不是集合。

以下示例按性别将集合roster的成员分组:

Map> byGender =

roster

.stream()

.collect(

Collectors.groupingBy(Person::getGender));

groupingBy操作返回一个map,其键是应用指定为其参数的lambda表达式(称为分类函数)所得到的值。在本例中,返回的map包含两个键,Person.Sex.MALE和Person.Sex.FEMALE,键对应的值是List的实例,其中包含流元素,当分类函数处理这些元素时,这些元素与键值对应。例如,与键Person.Sex.MALE对应的值是一个包含所有男性成员的List实例。

以下示例检索集合roster中每个成员的姓名,并按性别将其分组:

Map> namesByGender =

roster

.stream()

.collect(

Collectors.groupingBy(

Person::getGender,

Collectors.mapping(

Person::getName,

Collectors.toList())));

本例中的groupingBy操作接受两个参数,一个分类函数和一个Collector实例,Collector参数称为下游收集器,这是Java运行时应用于另一个收集器的结果的收集器。因此,这个groupingBy操作使你能够对groupingBy操作符创建的List值应用collect方法。此示例应用收集器mapping,它将mapping函数Person::getName应用于流的每个元素。因此,产生的流只包含成员的名称,包含一个或多个下游收集器的管道(如本例)称为多级归纳。

下面的示例检索每种性别成员的总年龄:

Map totalAgeByGender =

roster

.stream()

.collect(

Collectors.groupingBy(

Person::getGender,

Collectors.reducing(

0,

Person::getAge,

Integer::sum)));

reducing操作需要三个参数:

identity:如Stream.reduce操作,如果流中没有元素,则identity元素既是归纳的初始值,也是缺省结果,在这个例子中,identity元素是0,这是年龄总和的初始值,如果不存在成员,则为默认值。

mapper:reducing操作将此mapper函数应用于所有流元素,在本例中,mapper检索每个成员的年龄。

operation:operation函数用于归纳映射值,在本例中,operation函数添加Integer值。

下面的例子检索了每种性别成员的平均年龄:

Map averageAgeByGender = roster

.stream()

.collect(

Collectors.groupingBy(

Person::getGender,

Collectors.averagingInt(Person::getAge)));

java聚合_Java™ 教程(聚合归纳操作)相关推荐

  1. java 聚合_Java 8 聚合操作详解

    Oracle在2014年3月19日如期发布了Java 8.Java 8版本被认为是具有里程碑意义的一个版本,Oracle在该版本中添加了许多新特性,包括Lambda表达式.方法引用.加强了安全等等. ...

  2. java 数据聚合_Java数据聚合问题请教?

    时间: 2021-01-07 02:38:41 标签: javascript Java数据聚合问题 public class Demo {public static void main(String[ ...

  3. java的聚合_java中聚合是什么

    java中聚合是一种特殊的关联形式,它是两个类之间的关系,是一种HAS-A关系,是一种单向关联.如果类具有实体引用,则称为聚合. 举个例子:在一个有这么两个类Studentclass和Addressc ...

  4. java 日期_Java中的日期操作

    Date : getTime() .setTime() SimpleDateFormate :   Formate(Date). parse(String s) Calendar : getInsta ...

  5. java依赖_java 依赖、组合、聚合与继承

    java中类与类之间的关系 大部分的初学者只知道java中两个类之间可以是继承与被继承的关系,可是事实上,类之间的关系大体上存在五种-继承(实现).依赖.关联.聚合.组合. 接下来,简单的分析一下这些 ...

  6. Elasticsearch实战(十三)---聚合搜索Aggs聚合及Count,Avg操作

    Elasticsearch实战- 聚合搜索Aggs聚合及Count,Avg操作 文章目录 Elasticsearch实战- 聚合搜索Aggs聚合及Count,Avg操作 1.聚合搜索 bucket 桶 ...

  7. Elasticsearch(三)——Es搜索(简单使用、全文查询、复合查询)、地理位置查询、特殊查询、聚合操作、桶聚合、管道聚合

    Elasticsearch(三)--Es搜索(简单使用.全文查询.复合查询).地理位置查询.特殊查询.聚合操作.桶聚合.管道聚合 一.Es搜索 这里的 Es 数据博主自己上网找的,为了练习 Es 搜索 ...

  8. Elasticsearch Java API 分组、聚合、嵌套相关查询

    Elasticsearch Java API 分组.聚合.嵌套相关查询 翼支付监控系统正使用es做后端存储,这边我们是将日志计算处理过后的数据通过kafka储存到es.选择用es作为数据储存端是考虑到 ...

  9. Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~

    Java后端进行经纬度点抽稀聚合,HTML呈现及前端聚合实现点聚合~ 1. 效果图~ 1.1 前端实现聚合及呈现 1.2 后端实现点聚合,前端渲染呈现效果图 2. 原理 3. 源码 3.1 前端JS实 ...

最新文章

  1. python可选参数位置_每个位置参数的可选参数
  2. ORA-15260: permission denied on ASM disk group
  3. [九度][何海涛] 跳台阶
  4. 第三个一千行+500行总结-数据结构C复习--知识点总结3--七到九章
  5. 两教授吐槽:如今博士研究生的论文写作水平为何如此堪忧?
  6. passive模式 tcp_FTP主动模式和被动模式的比较
  7. 关于复旦大学英语水平测试和计算机应用能力水平测试成绩记载事宜的说明,复旦大学水平测试(FCT、FET)近期通知概览 | 一周复旦热问...
  8. 窥探Swift之别样的枚举类型
  9. 中断占据CPU时间的计算问题
  10. ofo容器pass架构分享
  11. 一文讲解ARM、STM32之间的关系以及STM单片机介绍
  12. 软考软件设计师(知识产权)
  13. 舱机器人尾巴毛茸茸_『新奇玩意』毛茸茸的机器人不仅可撸,还会摇尾巴
  14. 利用第三方Cookie和iframe完成广告显示(各大网站就是利用了第三方Cookie和iframe来显示百度和京东的广告)
  15. 我们为什么用GO语言来做区块链?
  16. 如何提升公众号的阅读量?提高公众号阅读量的方法介绍
  17. [免费专栏] Android安全之数据存储与数据安全「详解」
  18. 房地产楼盘三维展示|户型3D展示效果
  19. SEO外链策略之链接诱饵的制作需知
  20. 高频功率放大器损耗电阻怎么计算

热门文章

  1. cocos2dx windows phone平台下CCLabelTTF自己主动换行的实现
  2. 读大道至简——编程的精义感想
  3. 全心加入web前端开发,向上吧!
  4. jquery一些 事件的用法
  5. 计算纯文本情况下RichTextBox实际高度的正确方法(.NET)
  6. 数据结构 3优先队列(堆)
  7. [转载] python关键字和保留字_Python关键字
  8. [转载] python判断是否为json_Python判断变量是否为Json格式的字符串示例
  9. [转载] [Python] np.ones_like(ndarray)和np.zeros_like(ndarray)
  10. [转载] 语言程序设计第4版黄洪艺_计算机二级教程 Python语言程序设计 第8章python计算生态...