前言:为很好的理解这些方法,你需要熟悉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. (线段树)A Corrupt Mayor's Performance Art

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 题意: 区间更新, 区间询问: 题解: 区间更新, 区间询问, 一共30种颜色, 可用int 来 ...

  2. TCP/IP网络基础知识

    TCP/IP是一组用于实现网络互联的通信协议,通常称为TCP/IP协议族.包括TCP.IP.UDP.ICMP.RIP.TELNETFTP.SMTP.ARP.TFTP等. 一.TCP/IP模型将协议分为 ...

  3. hopper逆向的伪代码令人大跌眼镜

    网上介绍hopper有逆向伪代码的文章很多,并以为其是万能而且cool B的.但是并没有人去求证hopper的逆向伪代码参考系数(参考价值,大家做过开发都清楚明白,有些功能看起来很花很cool但不实用 ...

  4. vue3.0wactch监听

    <template> <div> <input v-model="count" /> </div> </template> ...

  5. web前端之css基础

    CSS选择器 元素选择器 p{color:red;} ID选择器 #li{ background-color:red; } 类选择器 .c1{ font-size:15px; } 注意: 样式类名不要 ...

  6. day 17 re模块 正则表达式

    import re    引用re模块 查找 finall:匹配所有,每一项都是列表中的一个元素 search:只匹配从左到右的第一个,得到的不是直接的结果而是一个变量,通过group方法获取结果,没 ...

  7. SQL语句实用技巧1

    --显示行号 select *, ROW_NUMBER() OVER(Order by TYPENAME ) AS RowNumber from ( select distinct TYPENAME ...

  8. PowerMock学习(十一)之Mock private methods的使用

    Mock  private methods 就是mock私有方法啦,学到这不难发现,我们其实大部分都是通过反射去完成单元测试的,但是在实际中,某个类中的私有方法,个人不建议使用反射来测试,因为有时候会 ...

  9. 4.Netty执行IO事件和非IO任务

    回顾NioEventLoop的run方法流程 IO事件与非IO任务 处理IO事件 处理非IO任务 聚合定时任务到普通任务队列 从普通队列中获取任务 计算任务执行的超时时间 安全执行 计算是否超时 总结 ...

  10. MySQL 库、表、记录、相关操作(3)

    MySQL 库.表.记录.相关操作(3) 单表查询 """ 增: insert [into] [数据库名.]表名[(字段1[, ..., 字段n])] values (数 ...