Java
Streams
Integer
Java 8
Method References

Why do .maxIntegermax and .minIntegermin compile on a Java 8 Stream?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

In Java 8, the Streams API was introduced to provide a functional approach to processing sequences of elements. One of the key features of Streams is the ability to aggregate data using reduction operations. In this article, we will explore how and why the methods .max(Integer::max) and .min(Integer::min) successfully compile and operate on Java Streams, diving into the technical explanations of method references and functional interfaces.

Concepts and Components

Before diving into the specifics of .max(Integer::max) and .min(Integer::min), it is essential to understand some foundational Java concepts:

  1. Streams: Streams represent a sequence of elements and support different kinds of operations to perform computations with those elements.
  2. Reduction Operations: These operations are used to combine the elements of a stream into a single result, such as finding the sum, the maximum, or the minimum.
  3. Method References: Introduced in Java 8, method references provide a way to refer to methods without invoking them. They are used to create lambda expressions and can be used with static methods, instance methods, and constructors.
  4. Functional Interfaces: A functional interface is an interface that contains a single abstract method. In the context of streams, functional interfaces define the operations to be performed in a stream.

How .max(Integer::max) and .min(Integer::min) Work

Method Reference

The expressions Integer::max and Integer::min are examples of static method references. They point to the static methods max and min defined in the Integer class.

java
1public static int max(int a, int b) {
2    return (a >= b) ? a : b;
3}
4
5public static int min(int a, int b) {
6    return (a <= b) ? a : b;
7}

Reduction Using max and min

The Stream class provides max and min methods that facilitate reduction operations:

  • Optional<T> max(Comparator<? super T> comparator)
  • Optional<T> min(Comparator<? super T> comparator)

These methods require a Comparator to determine the maximum or minimum element of the stream. However, Integer::max and Integer::min are often mistakenly assumed to directly correspond to these methods. Instead, they are typically used with the reduce method.

Example with reduce

The reduce method can take an associative function to reduce the elements of a stream.

For example:

java
1List<Integer> numbers = Arrays.asList(3, 5, 1, 2, 9);
2
3Optional<Integer> maxVal = numbers.stream().reduce(Integer::max);
4Optional<Integer> minVal = numbers.stream().reduce(Integer::min);
5
6System.out.println("Max: " + maxVal.orElseThrow());
7System.out.println("Min: " + minVal.orElseThrow());

Here, Integer::max and Integer::min serve as BinaryOperators which are functional interfaces. They take two inputs of the same type and return a result of that type.

Why They Compile

  1. BinaryOperator Functional Interface: Both Integer::max and Integer::min are compatible with BinaryOperator<Integer>, a specialization of BiFunction<T, U, R>. The reduce method uses this to accumulate stream elements into a single result.
  2. Static Method Reference Compatibility: The method references Integer::max and Integer::min match the signature int apply(int a, int b), thus compatible with the BinaryOperator<Integer> interface.

Key Points Summary

Concept / MethodDescription
StreamsJava 8 feature for processing sequences of elements.
ReductionCombines elements into a single result.
Method ReferenceInteger::max and Integer::min point to static methods. Used as BinaryOperator.
reduce MethodAccepts a BinaryOperator to reduce stream.
max & min MethodsUse Comparator for stream element comparison.

Additional Exploration

Comparator and Method References

While method references like Integer::max can't be directly used with the max and min methods that require comparators, custom comparators can use lambda expressions:

java
Comparator<Integer> comp = (a, b) -> Integer.compare(a, b);
Optional<Integer> maxVal = numbers.stream().max(comp);

Handling Empty Streams

Using reduce or finding the max and min on streams returns an Optional because streams may be empty. Handling this scenario is crucial:

java
Optional<Integer> maxVal = numbers.stream().reduce(Integer::max);
maxVal.ifPresent(System.out::println); // Handle empty case gracefully.

Concluding Thoughts

The use of .max(Integer::max) and .min(Integer::min) in Java 8 streams showcases the power of method references and functional programming in Java. By leveraging functional interfaces like BinaryOperator, developers can write concise and expressive code to process and aggregate data in streams efficiently. As you explore the Streams API further, keep in mind the flexibility and adaptability of Java's lambda expressions and method references in functional programming.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.