java 流计算_Java 流收集器 ( Stream Collectors ) ( 一 ) - 统计计算

首先需要声明的是,我的开发语言是 PHP,但我对所有语言都懂一点点,然后很多文章,都是看到某个知识点就想写些什么

刚刚再浏览某些文章的时候看到 Java 的流收集器 ( Stream Collectors ),哈哈,瞬间感兴趣,流收集器,光这四个大字看起来就有点高大上的直觉

流收集器 ( Stream Collectors )

众所周知,流 ( Stream ) 是 Java 8 引入的一个新的抽象,让我们可以以声明的方式处理数据。此外,流天生可以利用多核构架,而无需编写单线多线程代码

Collectors 是 Collector 接口的一个实现类,它实现了各种有用的 reduce 操作,例如将元素累积到集合中,根据各种标准汇总元素等

引入命令空间

对了,为了方便演示,我们直接用单个文件来演示,文件名为 MyCollectors.java

MyCollectors.java

import java.util.Arrays;

import java.util.List;

import java.util.Comparator;

import java.util.stream.Collectors;

使用 Collectors 类

为了演示流收集器 Collectors 的用法,我们首先定义一个雇员类 Employee 来保存数据

MyCollectors.java

import java.util.Arrays;

import java.util.List;

import java.util.stream.Collectors;

class Employee {

private String empId;

private String name;

private Double salary;

private String department;

public Employee(String empId, String name, Double salary, String department) {

this.empId = empId;

this.name = name;

this.salary = salary;

this.department = department;

}

public String getEmpId() {

return empId;

}

public void setEmpId(String id ) {

empId = id;

}

public String getName() {

return name;

}

public void setName(String myname ) {

name = myname;

}

public Double getSalary() {

return salary;

}

public void setSalary(double mysalary) {

salary = mysalary;

}

public String getDepartment() {

return department;

}

public void setDepartment(String mydepartment ) {

department = mydepartment;

}

public String toString() {

return "Employee(" + empId + "," + name + "," + salary.toString() + "," + department + ")";

}

}

然后,我们创建多个 Employee 类的实例,并把它们都放到列表 employees 中

class MyCollectors {

public static void main(String[] args) {

Employee john = new Employee("E123", "John Nhoj", 200.99, "IT");

Employee south = new Employee("E223", "South Htuos", 299.99, "Sales");

Employee reet = new Employee("E133", "Reet Teer", 300.99, "IT");

Employee prateema = new Employee("E143", "Prateema Rai", 300.99, "Benefits");

Employee yogen = new Employee("E323", "Yogen Rai", 200.99, "Sales");

List employees = Arrays.asList(john, south, reet, prateema, yogen);

System.out.println(employees);

}

}

使用命令 javac MyCollectors.java && java MyCollectors 运行,输出结果如下

$ javac MyCollectors.java && java MyCollectors

[Employee(E123,John Nhoj,200.99,IT), Employee(E223,South Htuos,299.99,Sales), Employee(E133,Reet Teer,300.99,IT), Employee(E143,Prateema Rai,300.99,Benefits), Employee(E323,Yogen Rai,200.99,Sales)]

好,有了演示数据就好办了,接下来我们使用流收集器来做一些有趣的操作

Collectors.averagingDouble 求取所有雇员薪水的平均数

Double averageSalary = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));

System.out.println(averageSalary);

输出结果 260.79

相类似的方法还有

求取 Integer 类型的平均值

public static Collector averagingInt(ToIntFunction super T> mapper)

求取 Long 类型的平均值

public static Collector averagingLong(ToLongFunction super T> mapper)

Collectors.summingDouble() 求取所有雇员薪水的总额

Double totalSalary = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));

System.out.println(totalSalary);

输出结果为 1303.95

同样的,相类似的方法还有

求取 Interger 类型的总和

public static Collector summingInt(ToIntFunction super T> mapper)

求取 Long 类型的总和

public static Collector summingLong(ToLongFunction super T> mapper)

查找薪水最大值的雇员

为了查找薪水的最大值,我们就要做以系列的调用了

Double maxSalary = employees.stream().collect(Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)), emp -> emp.get().getSalary()));

System.out.println(maxSalary);

输出结果为 300.99

这个调用看起来适不适合很头晕 ? 又长又臭

collectingAndThen() 方法收集收据,使用第二个参数来格式化数据,然后再传递给第一个参数来处理,原型如下

Collector collectingAndThen(Collector downstream, Function finisher)

其中第二个参数 finisher 用于格式化数据,比如我们求取薪水的平均值,并添加美元符号和保留 3 位小数,那么可以使用下面的语句

String avgSalary2 = employees.stream().collect(Collectors.collectingAndThen(Collectors.averagingDouble(Employee::getSalary), new DecimalFormat("$0.000")::format));

System.out.println(avgSalary2);

输出结果为 $260.790

对了,使用 DecimalFormat 需要引入类 java.text.DecimalFormat

一次性统计平均值,总和,最大值,最小值 Collectors.summarizingDouble

我们可以使用 Collectors.summarizingDouble() 函数一次性统计 Double 类型数据的平均值,总和,最大值,最小值

DoubleSummaryStatistics statistics = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));

System.out.println("Average: " + statistics.getAverage() + ", Total: " + statistics.getSum() + ", Max: " + statistics.getMax() + ", Min: "+ statistics.getMin());

输出结果为 Average: 260.79, Total: 1303.95, Max: 300.99, Min: 200.99

Collectors.summarizingDouble() 方法返回的是 DoubleSummaryStatistics 类型的实例,所以需要引入类 java.util.DoubleSummaryStatistics

相类似的方法还有

一次性计算 Integer 类型的统计信息

public static Collector summarizingInt(ToIntFunction super T> mapper)

一次新计算 Long 类型的统计信息

public static Collector summarizingLong(ToLongFunction super T> mapper)

结束语

本章节已经有点长了,我们就到此结束吧,贴上以上范例的所有代码

import java.util.Arrays;

import java.util.List;

import java.util.Comparator;

import java.text.DecimalFormat;

import java.util.stream.Collectors;

import java.util.DoubleSummaryStatistics;

class Employee {

private String empId;

private String name;

private Double salary;

private String department;

public Employee(String empId, String name, Double salary, String department) {

this.empId = empId;

this.name = name;

this.salary = salary;

this.department = department;

}

public String getEmpId() {

return empId;

}

public void setEmpId(String id ) {

empId = id;

}

public String getName() {

return name;

}

public void setName(String myname ) {

name = myname;

}

public Double getSalary() {

return salary;

}

public void setSalary(double mysalary) {

salary = mysalary;

}

public String getDepartment() {

return department;

}

public void setDepartment(String mydepartment ) {

department = mydepartment;

}

public String toString() {

return "Employee(" + empId + "," + name + "," + salary.toString() + "," + department + ")";

}

}

class MyCollectors {

public static void main(String[] args) {

Employee john = new Employee("E123", "John Nhoj", 200.99, "IT");

Employee south = new Employee("E223", "South Htuos", 299.99, "Sales");

Employee reet = new Employee("E133", "Reet Teer", 300.99, "IT");

Employee prateema = new Employee("E143", "Prateema Rai", 300.99, "Benefits");

Employee yogen = new Employee("E323", "Yogen Rai", 200.99, "Sales");

List employees = Arrays.asList(john, south, reet, prateema, yogen);

System.out.println(employees);

Double averageSalary = employees.stream().collect(Collectors.averagingDouble(Employee::getSalary));

System.out.println(averageSalary);

Double totalSalary = employees.stream().collect(Collectors.summingDouble(Employee::getSalary));

System.out.println(totalSalary);

Double maxSalary = employees.stream().collect(Collectors.collectingAndThen(Collectors.maxBy(Comparator.comparingDouble(Employee::getSalary)), emp -> emp.get().getSalary()));

System.out.println(maxSalary);

String avgSalary2 = employees.stream()

.collect(Collectors.collectingAndThen(Collectors.averagingDouble(Employee::getSalary), new DecimalFormat("$0.000")::format));

System.out.println(avgSalary2);

DoubleSummaryStatistics statistics = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));

System.out.println("Average: " + statistics.getAverage() + ", Total: " + statistics.getSum() + ", Max: " + statistics.getMax() + ", Min: "+ statistics.getMin());

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值