前言:为很好的理解这些方法,你需要熟悉java8特性Lambda和方法引用的使用

一:简介

  我们用集合的目的,往往不是简单的仅仅把数据保存哪里。而是要检索(遍历)或者去计算或统计....操作集合里面的数据。现假设我有一个实体对象Person如下,用于测试集合操作

public class Person {
public enum Sex {
MALE, FEMALE
}
String name;
LocalDate birthday;
Sex gender;
String emailAddress; Person(String nameArg, LocalDate birthdayArg, Sex genderArg, String emailArg) {
name = nameArg;
birthday = birthdayArg;
gender = genderArg;
emailAddress = emailArg;
} public int getAge() {
return birthday.until(IsoChronology.INSTANCE.dateNow()).getYears();
} public void printPerson() {
System.out.println(name + ", " + this.getAge());
} public Sex getGender() {
return gender;
} public String getName() {
return name;
} public String getEmailAddress() {
return emailAddress;
} public LocalDate getBirthday() {
return birthday;
} public static int compareByAge(Person a, Person b) {
return a.birthday.compareTo(b.birthday);
} public static List<Person> createRoster() { List<Person> roster = new ArrayList<>();
roster.add(new Person("Fred", IsoChronology.INSTANCE.date(1980, 6, 20), Person.Sex.MALE, "fred@example.com"));
roster.add(new Person("Jane", IsoChronology.INSTANCE.date(1990, 7, 15), Person.Sex.FEMALE, "jane@example.com"));
roster.add(
new Person("George", IsoChronology.INSTANCE.date(1991, 8, 13), Person.Sex.MALE, "george@example.com"));
roster.add(new Person("Bob", IsoChronology.INSTANCE.date(2000, 9, 12), Person.Sex.MALE, "bob@example.com")); return roster;
} @Override
public String toString() {
return "Person [name=" + name + ", birthday=" + birthday + ", gender=" + gender + ", emailAddress="
+ emailAddress + "]";
} }

1.1 管道和流

NOTE: 管道是一个有序的聚合操作(A pipeline is a sequence of aggregate operations)

举例一:打印集合中所有性别为男性的名字

@Test
public void test1() {
roster.stream().filter(e -> e.getGender() == Person.Sex.MALE).forEach(e -> System.out.println(e.getName()));
}

当然你也可以用 for-each 循环做到这一点

分析:管道中包含了那些组件

一个数据源,即一个集合 roster

0个或多个中间操作,本例中只有一个.filter过滤集合中的男性。

一个终止操作,即forEach遍历并打印姓名,无返回值。

举例二:计算平均数,即计算集合中男性的平局年龄

@Test
public void test() {
double average = roster.stream().filter(p -> p.getGender() == Person.Sex.MALE).mapToInt(Person::getAge)
.average().getAsDouble();
System.out.println(average);
}

聚合过程  filter-->mapToInt-->average()-->getAsDouble

二:还原操作

Note:The JDK contains many terminal operations (such as averagesumminmax, and count) that return one value by combining the contents of a stream. These operations are called reduction operations.

还原操作:个人理解还原操作即一种终止某种过程或状态的操作,并转换成另外一种状态。在这里即是对流的终止操作,并转化为另一种状态(另一种状态即Double或Int....包括引用类型)

这里主要介绍两种  Stream.reduce和Stream.collect方法。

2.1:Stream.reduce 计算总和

方法一:通过sum() 聚合   roster.stream().mapToInt(Person::getAge).sum();

方法二:即通过Stream.reduce

Integer totalAgeReduce = roster.stream().map(Person::getAge).reduce(0, (a, b) -> a + b);

NOTE: 0 可以改为任意Int数据,其作用就是在原总和的基础上加上0

2.2 :Stream.collect方法 还原成其他类型

举例一:计算平均数,还原成指定类型Averager

public class Averager implements IntConsumer {
private int total = 0;
private int count = 0; public double average() {
return count > 0 ? ((double) total) / count : 0;
} public double getTotal() {
return total;
} @Override
public void accept(int i) {
total += i;
count++;
} public void combine(Averager other) {
total += other.total;
count += other.count;
}
}

测试:

@Test
public void test3() {
SupplierImpl impl = new SupplierImpl();
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()); Averager averageCollect2 = roster.stream().filter(p -> p.getGender() == Person.Sex.MALE).map(Person::getAge)
.collect(impl, Averager::accept, Averager::combine);
System.out.println("Average age of male members22: " + averageCollect2.average());
}

The collect operation in this example takes three arguments:

  • supplier: The supplier is a factory function; it constructs new instances. For the collect operation, it creates instances of the result container. In this example, it is a new instance of the Averager class.
  • accumulator: The accumulator function incorporates a stream element into a result container. In this example, it modifies the Averager result container by incrementing the count variable by one and adding to the totalmember variable the value of the stream element, which is an integer representing the age of a male member.
  • combiner: The combiner function takes two result containers and merges their contents. In this example, it modifies an Averager result container by incrementing the count variable by the count member variable of the other Averager instance and adding to the total member variable the value of the other Averager instance's total member variable

举例二:Stream.collect方法 还原成List<String>

@Test
public void test5() {
List<String> namesOfMaleMembersCollect = roster.stream().filter(p -> p.getGender() == Person.Sex.MALE)
.map(p -> p.getName()).collect(Collectors.toList());
namesOfMaleMembersCollect.forEach(System.out::print);
System.out.println();
namesOfMaleMembersCollect.add("1234");
namesOfMaleMembersCollect.forEach(System.out::print);
}

举例三:Stream.collect方法  还原成Map<Object,List<Object>,

@Test
public void test6() {
Map<Sex, List<Person>> byGender = roster.stream().collect(Collectors.groupingBy(Person::getGender));
Set<Sex> keySet = byGender.keySet();
for (Sex sex : keySet) {
List<Person> list = byGender.get(sex);
System.out.println("sex = " + sex);
list.forEach(System.out::print);
System.out.println();
}
}

使用场景:对源数据进行分组

举例四:Stream.collect方法  还原成Map<Object,List>,

@Test
public void test7() {
Map<Person.Sex, List<String>> namesByGender = roster.stream().collect(
Collectors.groupingBy(Person::getGender, Collectors.mapping(Person::getName, Collectors.toList())));
Set<Sex> keySet = namesByGender.keySet();
for (Sex sex : keySet) {
List<String> list = namesByGender.get(sex);
System.out.println("sex = " + sex);
list.forEach(System.out::print);
System.out.println();
}
Map<Person.Sex, List<String>> namesByGender2 = roster.stream().collect(Collectors.groupingBy((p) -> {
return p.getGender();
}, Collectors.mapping(Person::getName, Collectors.toList())));
Set<Sex> keySet2 = namesByGender2.keySet();
for (Sex sex : keySet2) {
List<String> list = namesByGender2.get(sex);
System.out.println("sex = " + sex);
list.forEach(System.out::print);
System.out.println();
}
}

举例五:Stream.collect方法,分组并求和

@Test
public void test8() {
Map<Person.Sex, Integer> totalAgeByGender = roster.stream().collect(
Collectors.groupingBy(Person::getGender, Collectors.reducing(0, Person::getAge, Integer::sum)));
Set<Sex> keySet2 = totalAgeByGender.keySet();
for (Sex sex : keySet2) {
Integer integer = totalAgeByGender.get(sex);
System.out.println("sex = " + sex);
System.out.println("年龄sum = " + integer); }
}

举例六:Stream.collect方法,分组并计算平均数

 @Test
public void test9() {
Map<Person.Sex, Double> averageAgeByGender = roster.stream()
.collect(Collectors.groupingBy(Person::getGender, Collectors.averagingInt(Person::getAge)));
Set<Sex> keySet2 = averageAgeByGender.keySet();
for (Sex sex : keySet2) {
Double double1 = averageAgeByGender.get(sex);
System.out.println("sex = " + sex);
System.out.println("年龄avg = " + double1);
}
}        

三 并行操作(Parallelism)

llll 

大数据项目2(Java8聚合操作)的更多相关文章

  1. 大数据项目实践:基于hadoop+spark+mongodb+mysql+c#开发医院临床知识库系统

    一.前言 从20世纪90年代数字化医院概念提出到至今的20多年时间,数字化医院(Digital Hospital)在国内各大医院飞速的普及推广发展,并取得骄人成绩.不但有数字化医院管理信息系统(HIS ...

  2. 大数据项目测试<二>项目的测试工作

    大数据的测试工作: 1.模块的单独测试 2.模块间的联调测试 3.系统的性能测试:内存泄露.磁盘占用.计算效率 4.数据验证(核心) 下面对各个模块的测试工作进行单独讲解. 0. 功能测试 1. 性能 ...

  3. 大数据项目之_15_电信客服分析平台_03&04_数据分析

    3.3.数据分析3.3.1.Mysql 表结构设计3.3.2.需求:按照不同的维度统计通话3.3.3.环境准备3.3.4.编写代码:数据分析3.3.5.运行测试3.3.6.bug 解决 3.3.数据分 ...

  4. 大数据项目相关技术栈(Hadoop周边技术)

    J2EE 框架Spring 开发框架 + SSH or SSM Lucene 索引和查询IKAnalyzer 分词Webmagic 爬虫 ETL工具:KettleSqoop 结构化数据库-hadoop ...

  5. Mysql备份系列(3)--innobackupex备份mysql大数据(全量+增量)操作记录

    在日常的linux运维工作中,大数据量备份与还原,始终是个难点.关于mysql的备份和恢复,比较传统的是用mysqldump工具,今天这里推荐另一个备份工具innobackupex.innobacku ...

  6. 如何在IDEA里给大数据项目导入该项目的相关源码(博主推荐)(类似eclipse里同一个workspace下单个子项目存在)(图文详解)

    不多说,直接上干货! 如果在一个界面里,可以是单个项目 注意:本文是以gradle项目的方式来做的! 如何在IDEA里正确导入从Github上下载的Gradle项目(含相关源码)(博主推荐)(图文详解 ...

  7. 大数据项目(MTDAP)随想

    Spark MLlib进行example测试的时候,总是编译不通过,报少包<Spark MLlib NoClassDefFoundError: org/apache/spark/ml/param ...

  8. 大数据项目之_15_电信客服分析平台_01&02_项目背景+项目架构+项目实现+数据生产+数据采集/消费(存储)

    一.项目背景二.项目架构三.项目实现3.1.数据生产3.1.1.数据结构3.1.2.编写代码3.1.3.打包测试3.2.数据采集/消费(存储)3.2.1.数据采集:采集实时产生的数据到 kafka 集 ...

  9. 华为大数据项目fusionInsight

    项目简述:基于开源Hadoop2.0架构的集群网络,进行海量数据的分布式计算.由于Hadoop集群规模不断扩大,而搭建一个同等规模的测试集群需要一笔昂贵的开销.目前有100台左右物料,期望预测计算节点 ...

随机推荐

  1. vue cli3.0 封装组件全局引入js文件并发布到npm

    首先用 vue create创建一个项目 当前的项目目录是这样的: 首先需要创建一个 packages 目录,用来存放组件 然后将 src 目录改为 examples 用作示例 二.修改配置 启动项目 ...

  2. 迁移桌面程序到MS Store(12)——WPF使用UWP InkToolbar和InkCanvas

    我们在<迁移桌面程序到MS Store(4)——桌面程序调用Win10 API>提到了对Win10 API的调用,但仍存在无法在WPF中使用UWP控件的问题,虽然都是XAML控件,但却是两 ...

  3. 学习PHP框架只停留在会用层面,职业生涯肯定走不远!

    工作这么多年,也面试过很多PHP工程师,我发现很多PHP工程师只停留在使用框架的层面,然而对框架底层根本没有深入去了解,那么这就会给自己的职业生涯带来一定的瓶颈,当遇到问题的时候你就无从下手,不知道如 ...

  4. Dart Learn Notes 04

    流程控制语句 流程控制语句的作用就是控制代码的执行流程. if and else var a = 10; if(a > 10){ print('ok'); }else if( 5 < a ...

  5. 【笔记】总结Springboot和Vue前后端分离的跨域问题

    跨域一直是个很玄学的问题,SSM的时候又得前后端一起配置,sb的时候又不用. 前端 axios普通get请求 submitForm() { var v=this; this.$axios({ meth ...

  6. Flow入门初识

    Flow是facebook出品的JavaScript静态类型检查工具. 由于JavaScript是动态类型语言,它的灵活性也会造成一些代码隐患,使用Flow可以在编译期尽早发现由类型错误引起的bug, ...

  7. 2场 J -Subarray

    题意: 长度为1e91e9的(1,−1)(1,−1)序列,下标从00到1e9−11e9−1,已知有nn个区间为11,其他为−1−1, 问存在多少个区间的和>1>1(保证∑1≤i≤nr[i] ...

  8. 虚拟机中linux操作系统raid5(5块磁盘,3块做raid,2块做备份)配置流程及损坏磁盘的移除

    1.打开所要用的虚拟机,点击编辑虚拟机设置,点击硬盘,添加 2.一直点击下一步不做修改,直到最后完成 3.按照以上步骤添加5块磁盘 4.点击开启虚拟机,输入用户名root密码登录进去 5.进入虚拟机后 ...

  9. JS&jQuery

    1.JavaScript概述    1.什么是JavaScript        JavaScript简称JS,是一种专门运行于JS解释器/引擎中的解释型脚本语言    2.JS发展史         ...

  10. F#周报2019年第49期

    新闻 宣告.NET Core 3.1 新书:Kevin Avignon的F#提升效率 .NET Core 2.2将在2019年12月23日迎来终结 Visual Studio 16.5预览版1中升级了 ...