Question
Why does Java 8 Stream's .min() and .max() methods compile when using static methods from the Integer class instead of a Comparator?
final ArrayList <Integer> list = IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
System.out.println(list.stream().max(Integer::max).get());
System.out.println(list.stream().min(Integer::min).get());
Answer
In Java 8, the Stream API's .min() and .max() methods expect a Comparator as an argument. However, using static methods like Integer::max or Integer::min compiles due to type inference and the functional programming paradigm.
// Correct usage with a Comparator
System.out.println(list.stream().max(Comparator.naturalOrder()).get());
System.out.println(list.stream().min(Comparator.naturalOrder()).get());
Causes
- Java's method reference syntax allows for greater flexibility in the types of methods that can be used as arguments for functional interfaces.
- The method references Integer::max and Integer::min can be treated as Comparators because they comply with the functional interface's expected behavior, even though they aren't Comparators explicitly.
Solutions
- Use Comparator.comparingInt(Integer::intValue) to ensure clarity in your code and improve readability.
- Replace Integer::max and Integer::min with a proper Comparator to adhere to best practices and avoid confusion.
Common Mistakes
Mistake: Using static methods instead of Comparators without understanding their implications.
Solution: Always use a Comparator to avoid unintended behavior and make your code more comprehensible.
Mistake: Failing to handle the case where .min() or .max() might return an empty Optional.
Solution: Use Optional's isPresent() or use orElse() to provide a default value.
Helpers
- Java 8 streams
- .min() and .max() methods
- Integer static methods
- Java Comparators
- Stream API
- Java method references