前言:为很好的理解这些方法,你需要熟悉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. Java第09次实验(IO流)-实验报告

    0. 字节流与二进制文件 使用DataOutputStream与FileOutputStream将Student对象写入二进制文件student.data 二进制文件与文本文件的区别 try...ca ...

  2. Spring基于注解的配置1——@Required、@Autowired、@Qualifier示例及与传统注入方法的对比

    @Required注释 作用:用于属性的set方法,那么这个属性必须在xml文件的bean标签里面进行配置,否则就会抛出一个BeanInitializationException异常. 首先准备一个类 ...

  3. pyinstaller打包python文件成exe(原理.安装.问题)

    py文件打包成exe文件的方式一共有三种:py2exe.PyInstaller和cx_Freeze 本文分四个步骤来详讲如何用PyInstaller将py文件打包成exe文件 1. PyInstall ...

  4. Java通过 Scanner 类来获取用户的输入

    通过 Scanner 类来获取用户的输入. import java.util.Scanner; Scanner s = new Scanner(System.in);// 从键盘接收数据  Syste ...

  5. 金蝶天燕中间拒绝put、delete请求解决方案

    项目要求支持国产化,那就国产化呗!使用金蝶天燕中间件替代weblogic,一切部署好后发现所有以put.delete请求的按钮全部无效,原因是中间件配置文件默认拒绝put.delete请求 解决方案为 ...

  6. 浏览器中的 Event Loop

    当我们执行 JS 代码的时候其实就是往执行栈中放入函数,那么遇到异步代码的时候该怎么办?其实当遇到异步的代码时,会被挂起并在需要执行的时候加入到 Task(有多种 Task) 队列中.一旦执行栈为空, ...

  7. 【开发工具 - Git】之本地项目托管到远程仓库

    这里所说的“本地项目托管到远程仓库”,说的是:例如,我们在本地有一个写了很长时间的项目,现在想要托管到GitHub或码云上进行版本控制. 这个过程大致需要以下几个步骤: (1)在本地初始化Git项目本 ...

  8. Chapter 02—Creating a dataset(Part2)

    三. 导入数据 图02-03:Source of data that can be imported into a dataset 11. 从键盘导入数据 (1)可能是最简单的数据导入方式. (2)使 ...

  9. Spring Boot应用启动的三种方式

    Spring Boot应用HelloWorld的三种启动方式: 项目的创建可以在http://start.spring.io/网站中进行项目的创建. 首先项目结构: 1.  通过main方法的形式启动 ...

  10. rem布局方案

    移动端适配,老生常谈的问题,这次再谈一次. 闲话少说,直奔正题. 一些像素概念 物理像素:即实际的每一个物理像素,也就是移动设备上每一个物理显示单元(点) 设备逻辑像素(css中的px):可以理解为一 ...