Java 查找最大值和最小值,用户希望确定流中的最大值或最小值,既可以使用 BinaryOperator
接口定义的 maxBy
和 minBy
方法,也可以使用 Stream
接口定义的 max
和 min
方法,还可以使用 Collectors
类定义的 maxBy
和 minBy
方法。
Java 查找最大值和最小值 问题描述
用户希望确定流中的最大值或最小值。
Java 查找最大值和最小值 解决方案
既可以使用 BinaryOperator
接口定义的 maxBy
和 minBy
方法,也可以使用 Stream
接口定义的 max
和 min
方法,还可以使用 Collectors
类定义的 maxBy
和 minBy
方法。
Java 查找最大值和最小值 具体实例
BinaryOperator
是 java.util.function
包定义的一种函数式接口,它继承自 BiFunction
接口,适合在函数和返回值的参数属于同一个类时使用。
BinaryOperator
接口包括两种静态方法:
static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator)
static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator)
两种方法根据所提供的 Comparator
,返回一个 BinaryOperator
。
我们以一个 Employee
POJO 为例,讨论如何获取流的最大值。如例 4-24 所示,Employee
POJO 包括 name
、salary
与 department
这三个特性。
例 4-24
Employee
POJO
public class Employee {
private String name;
private Integer salary;
private String department;
// 其他方法
}
List<Employee> employees = Arrays.asList( ➊
new Employee("Cersei", 250_000, "Lannister"),
new Employee("Jamie", 150_000, "Lannister"),
new Employee("Tyrion", 1_000, "Lannister"),
new Employee("Tywin", 1_000_000, "Lannister"),
new Employee("Jon Snow", 75_000, "Stark"),
new Employee("Robb", 120_000, "Stark"),
new Employee("Eddard", 125_000, "Stark"),
new Employee("Sansa", 0, "Stark"),
new Employee("Arya", 1_000, "Stark"));
Employee defaultEmployee = ➋
new Employee("A man (or woman) has no name", 0, "Black and White");
❶ 员工集合
❷ 流为空时的默认值
给定一个由员工构成的集合,可以使用 Stream.reduce
方法,传入 BinaryOperator
作为参数。例 4-25 展示了如何查找工资最高的员工信息。
例 4-25
BinaryOperator.maxBy
方法的应用
Optional<Employee> optionalEmp = employees.stream()
.reduce(BinaryOperator.maxBy(Comparator.comparingInt(Employee::getSalary)));
System.out.println("Emp with max salary: " +
optionalEmp.orElse(defaultEmployee));
请注意,reduce
方法需要传入 BinaryOperator
作为参数。静态方法 maxBy
根据所提供的 Comparator
生成该 BinaryOperator
,并按工资高低对员工进行比较。
上述方案是可行的,不过采用 Stream.max
方法其实更简单,该方法可以直接应用于流:
Optional<T> max(Comparator<? super T> comparator)
例 4-26 显示了 max
方法的应用。
例 4-26
Stream.max
方法的应用
optionalEmp = employees.stream()
.max(Comparator.comparingInt(Employee::getSalary));
Stream.max
方法与 BinaryOperator.maxBy
方法的结果并无不同。
此外,几种基本类型流(IntStream
、LongStream
与 DoubleStream
)也提供一个不传入任何参数的 max
方法,其应用如例 4-27 所示。
例 4-27 查找最高工资
OptionalInt maxSalary = employees.stream()
.mapToInt(Employee::getSalary)
.max();
System.out.println("The max salary is " + maxSalary);
在本例中,mapToInt
方法通过调用 getSalary
方法将员工流转换为整数流,并返回 IntStream
。之后,Max
方法返回 OptionalInt
。
类似地,Collectors
工具类也定义了一种称为 maxBy
的静态方法,可以直接用于查找最高工资,如例 4-28 所示。
例 4-28
Collectors.maxBy
方法的应用
optionalEmp = employees.stream()
.collect(Collectors.maxBy(Comparator.comparingInt(Employee::getSalary)));
但是,Collectors.maxBy
方法不便处理,最好采用 Stream.max
方法作为替代(如例 4-27 所示)。Collectors.maxBy
方法在用作下游收集器(即对分组或分区操作进行后期处理)时相当有用。例 4-29 通过 Collectors.groupingBy
方法创建了一个部门到员工列表的映射,然后计算每个部门中工资最高的员工。
例 4-29
Collectors.maxBy
用作下游收集器
Map<String, Optional<Employee>> map = employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.maxBy(
Comparator.comparingInt(Employee::getSalary))));
map.forEach((house, emp) ->
System.out.println(house + ": " + emp.orElse(defaultEmployee)));
BinaryOperator.minBy
和 Collectors.minBy
方法的用法与相应的 maxBy
方法类似。