Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Java 8 Stream interface does not have min() no-parameter version?

java.util.stream.Stream interface has two versions of sorted method – sorted() which sorts elements in natural order and sorted(Comparator). Why min() method was not introduced to Stream interface, which would return minimal element from natural-ordering point of view?

like image 371
PresentProgrammer Avatar asked Dec 16 '17 20:12

PresentProgrammer


People also ask

How does stream API works in Java 8?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.

What is true about stream pipelining in Java 8?

Answer: Stream pipelining is the concept of chaining operations together. This is done by splitting the operations that can happen on a stream into two categories. They are "intermediate operations" and "terminal operations".

What does stream () do in Java?

With Java 8, Collection interface has two methods to generate a Stream. stream() − Returns a sequential stream considering collection as its source. parallelStream() − Returns a parallel Stream considering collection as its source.

Which of the following is correct about streams in Java 8?

i) Stream represents a sequence of objects from a source, which supports aggregate operations.


2 Answers

It should be clear that for min, max, and sorted, adding a method to Stream that does not require a comparator introduces a way to lose the generic type safety. The reason is that the current version of the Java language does not support restricting methods to instances of a specific parameterization, i.e. limit them to streams of comparable elements.

So the question could be the other way round, why has this potential break of the type safety been allowed with sorted()?

I can’t look into the developers mind, but one interesting point is that sorting has been treated specially for a long time now. With the introduction of Generics, it became possible to enforce that sorting without a Comparator can only be attempted for collections or arrays with comparable elements. However, especially when implementing generic collections, developers might face the fact that arrays can’t be created with a generic element type. There might be other scenarios, where a developer encounters an array or collection of a formally non-comparable type while the contained elements are comparable for sure. As said, I can’t look into the developers mind to say, which scenarios were considered.

But

  • Arrays.sort(Object[]) does not enforce the array type to be a subtype of Comparable. Even if it did,
  • sort(T[] a, Comparator<? super T> c) specifies that a null comparator implies “natural order”, which allows requesting natural order for any type
  • Collections.sort(List<T> list) requires a comparable element type, but
  • Collections.sort(List<T> list, Comparator<? super T> c) again specifies that a null comparator implies “natural order”, so there’s still an easy way to undermine the type system. Since the “null means natural” rule was already specified before Generics existed, it had to be kept for compatibility.

But it’s not just all about backwards compatibility. List.sort(Comparator), introduced in Java 8, is also specified as accepting null as argument for “natural order”, so now we have another scenario, where an implementer might have to sort data without a compile-time type that guarantees comparable elements.

So when it comes to sorting, there are already lots of opportunities to dodge the type system. But Stream.sorted(Comparator) is the only sort method not accepting a null comparator. So sorting by natural order without specifying Comparator.naturalOrder() is only possible using sorted() without arguments. By the way, having an already sorted input with a null comparator and requesting sorted() without comparator is the only situation where the Stream implementation will detect that sorting isn’t necessary, i.e. it doesn’t compare comparators and doesn’t check for Comparator.naturalOrder().

Generally, the type safety of comparators is astonishing weak. E.g. Collections.reverseOrder() returns a comparator of arbitrary type, not demanding the type to be comparable. So instead of min(), you could use max(Collections.reverseOrder()) to request the minimum, regardless of the stream’s formal type. Or use Collections.reverseOrder(Collections.reverseOrder()) to get the equivalent of Comparator.naturalOrder() for an arbitrary type. Likewise, Collator implements Comparator<Object>, for whatever reason, despite it can only compare Strings.

like image 200
Holger Avatar answered Oct 11 '22 12:10

Holger


I'd assume that would just pollute the API. one could say "why is there no max parameterless version", "why is there no CharStream" and it could on and on in terms of the things that could be made available but were decided best not to.

having a parameterless min method over this:

someList.stream().min(Comparator.naturalOrder());

would be no different.

therefore it's best to just create a reusable method rather than polluting the API with all the possible things.

like image 31
Ousmane D. Avatar answered Oct 11 '22 11:10

Ousmane D.