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
EmployeePOJO
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 方法类似。
极客教程