Java 8 Finding max/min with Collectors | maxBy, minBy methods tutorial with examples
Java 8 Determining maximum and minimum with Collectors tutorial explains, with examples, how to use the predefined
(Note - This tutorial assumes that you are familiar with basics of Java 8 CollectorsRead Tutorial explaining basics of Java 8 Collectors.) Predefined
AND
Where,
- input parameter is an instance of
- output is a
The predefined collectors returned by
Internally, these collectors delegate their tasks to the 'reducing collector' with the calls
OUTPUT of the above code
Explanation of the code
Summary
In this tutorial we understood the working of the predefined
Collectors
returned by java.util.Stream.Collectors
class' maxBy()
and minBy()
methods to find the maximum and minimum element of a given Stream
. The tutorial starts off with the formal definition of the maxBy(), minBy()
methods, then explains their working, and finally shows the methods' usage via a Java code example.(Note - This tutorial assumes that you are familiar with basics of Java 8 CollectorsRead Tutorial explaining basics of Java 8 Collectors.) Predefined
Collectors
returned by Collectors.maxBy()/Collectors.minBy()
methods
Collectors.maxBy()/minBy()
methods are defined with the following signatures - public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator)
AND
public static <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator)
- input parameter is an instance of
Comparator
of type T
- output is a
Collector
, acting on a Stream of elements of type T
, with its finisherClick to Read tutorial on 4 components of Collectors incl. 'finisher' returning the maximum(for maxBy()) or minimum(for minBy()) value from all the elements of the stream as an Optional
valueThe predefined collectors returned by
Collectors
class' maxBy()
/minBy()
methods get the maximum/minimum elements in the stream on which they are invoked using the Stream.collect()
method. The max/min value is returned as an Optional
value. This is because in case the stream has no elements then to avoid sending a bare null value which can result in a NullPointerException
, the value is sent as an Optional
.Collectors.maxBy()
/minBy()
methods are terminal operationsClick to Read Tutorial explaining intermediate & terminal Stream operations.reducing(BinaryOperator. maxBy(comparator))
and reducing(BinaryOperator. minBy(comparator))
for maximum/minimum element determination respectively. (Note that these calls to the reducing collector are internal to the implementation of the Collectors
class, and need not be a point of consideration for the end programmer using these methods.)
Java 8 code example showing Collectors.maxBy(),minBy()
methods' usage
Java 8 code example showing Collectors.maxBy()/minBy() usage
package com.javabrahman.java8.collector;
import com.javabrahman.java8.Employee;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
class MaxMinWithCollectors {
static List<Employee> employeeList
= Arrays.asList(new Employee("Tom Jones", 45, 15000.00),
new Employee("Tom Jones", 45, 7000.00),
new Employee("Ethan Hardy", 65, 8000.00),
new Employee("Nancy Smith", 22, 10000.00),
new Employee("Deborah Sprightly", 29, 9000.00));
public static void main(String[] args) {
Optional<Employee> maxSalaryEmp =
employeeList.stream()
.collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)));
System.out.println("Employee with max salary:"
+ (maxSalaryEmp.isPresent()? maxSalaryEmp.get():"Not Applicable"));
Optional<Employee> minAgeEmp =
employeeList.stream()
.collect(Collectors.minBy(Comparator.comparing(Employee::getAge)));
System.out.println("Employee with min age:"
+ (minAgeEmp.isPresent()? minAgeEmp.get():"Not Applicable"));
}
}
//Employee.java(POJO Class)
package com.javabrahman.java8;
import java.text.DecimalFormat;
public class Employee {
private String name;
private Integer age;
private Double salary;
public Employee(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
//Getters and Setters of name, age & salary go here
public String toString(){
DecimalFormat dformat = new DecimalFormat(".##");
return "Employee Name:"+this.name
+ " Age:"+this.age
+ " Salary:"+dformat.format(this.salary);
}
//Standard equals() and hashcode() implementations go here
}
Employee with max salary: Employee Name:Tom Jones Age:45 Salary:15000.0 Employee with min age: Employee Name:Nancy Smith Age:22 Salary:10000.0
Employee.java
is the POJO class i.e. the type of which theStream
is created. It contains 3 attributes -name
,age
andsalary
.MaxMinWithCollectors
class contains a static list of 5Employee
objects namedemployeeList
.- In the
main()
method ofMaxMinWithCollectors
class a stream ofEmployee
objects is created by invokingemployeeList.stream()
. This stream is then terminated by invoking thecollect()
method with theCollector
returned by theCollectors.maxBy()
method passed as a parameter. Collectors.maxBy()
method needs as its input parameter aComparator
instance. This Comparator instance is created using the Comparator.comparing()Click to Read Tutorial explaining Java 8 Comparators method with the sort key specified using the method referenceClick to Read Tutorial on Java 8 Method References to the getter ofsalary
attribute ofEmployee
class i.e. “Employee::getSalary
”.- As expected, the
Collector
returned byCollectors.maxBy()
method finds theEmployee
with the maximum salary and prints it as “Employee Name:Tom Jones Age:45 Salary:15000.0
”. Employee details are printed as per the formatting defined in the overriddentoString()
method in theEmployee
POJO class. As the maximum value is inside anOptional
, the code uses a ternary operator to first determine whether the value is present and then retrieves it. Else it returns theString
“Not Applicable”. - Similar to the maximum salary determination, employee with minimum age is identified by first creating a stream of
Employee
objects usingemployeeList.stream()
method.Stream.collect()
method is pipelinedClick to Read Tutorial explaining concept of Pipelines in Computing to thestream()
method, withCollectors.minBy()
as parameter.Collectors.minBy()
in turn takes aComparator
instance defined usingComparator.comparing()
method with getter toEmployee
’sage
attribute passed as sort key to it via the method reference “Employee::getAge
”. A ternary operator is used to check for presence ofOptional
minimum value before retrieving it. - As expected, the employee with minimum age is determined and printed as “
Nancy Smith Age:22 Salary:10000.0
”.
Collector
returned by the Collectors.maxBy()
and Collectors.maxBy()
methods. We looked at the formal definition of the Collectors.maxBy()
/Collectors.minBy()
methods, had a brief look at what actually happens inside the method, and finally saw the Collectors.maxBy()
/Collectors.minBy()
methods in action with a Java 8 code example followed by its explanation.Java 8 Collectors' Tutorials on JavaBrahman
Understanding Basics of Java 8 CollectorsClick to Read Tutorial explaining basics of Java 8 CollectorsCollectors.groupingBy()Click to Read Tutorial on Grouping with CollectorsCollectors.partitioningBy()Click to Read Partitioning using Collectors TutorialCollectors.counting()Click to Read Counting with Collectors TutorialCollectors.maxBy()/minBy()Click to Read Tutorial on finding max/min with CollectorsCollectors.joining()Click to Read Tutorial on joining as a String using CollectorsCollectors.collectingAndThen()Click to Read Tutorial on collectingAndThen CollectorCollectors.averagingInt() /averagingLong() /averagingDouble()Click to Read Tutorial on Averaging CollectorCollectors.toCollection()Click to Read Tutorial on Collectors.toCollection CollectorCollectors.mapping()Click to Read Tutorial on Mapping Collector
Understanding Basics of Java 8 CollectorsClick to Read Tutorial explaining basics of Java 8 CollectorsCollectors.groupingBy()Click to Read Tutorial on Grouping with CollectorsCollectors.partitioningBy()Click to Read Partitioning using Collectors TutorialCollectors.counting()Click to Read Counting with Collectors TutorialCollectors.maxBy()/minBy()Click to Read Tutorial on finding max/min with CollectorsCollectors.joining()Click to Read Tutorial on joining as a String using CollectorsCollectors.collectingAndThen()Click to Read Tutorial on collectingAndThen CollectorCollectors.averagingInt() /averagingLong() /averagingDouble()Click to Read Tutorial on Averaging CollectorCollectors.toCollection()Click to Read Tutorial on Collectors.toCollection CollectorCollectors.mapping()Click to Read Tutorial on Mapping Collector