Return Type Spliterator trySplit

I came across an interesting detail in java.util.Spliterator (Java 8).

The trySplit () method should return an instance of Spliterator or null if it cannot be split. The java document says the following:

  * @return a {@code Spliterator} covering some portion of the * elements, or {@code null} if this spliterator cannot be split. 

It seems like the perfect place to use java.util.Optional . According to javadoc:

  * A container object which may or may not contain a non-null value. 

Are there any reasons why optional was not used?

Googling did not help, except for this question on the lambda-dev mailing list, which it did not answer.

+5
source share
2 answers

There are several reasons why this is so. Of course, conceptually trySplit can return Optional<Spliterator<T>> , but there are some design forces that have pushed off of this.

One reason is that there is a difference between methods such as findFirst that return Optional versus methods such as trySplit that return or trySplit .

  • Methods such as findFirst call and return values ​​in the application code.
  • Methods of type trySplit call and return values ​​to the library code.

An aspect of designing JDK class libraries is that the library APIs (or should be) are designed to simplify application code, and library code often becomes more complex to make things easier for applications.

One of the main reasons for Optional is to avoid passing zeros from the library to the application code, since improper handling of errors is a common source of NullPointerException s. Instead of null APIs such as findFirst return an empty Optional , which is supported by a rich set of methods, such as orElse , map , filter , flatMap , etc., which provide more application flexibility to solve a problem that was not found.

Note that the nullable return value from trySplit goes in the opposite direction: from the application to the library.

The presence of application code that passes or returns a NULL value for the library is significantly less prone to errors for the application than receiving its value with a zero value from the library. If you are writing an application and the API says that you should pass or return zero to the library, there is no way that this will cause NPE to be created in your code. Indeed, there are many places in the API ( List.sort(null) ), where null has certain semantics in the API.

trySplit is called from a relatively small number of places in the library, and supporting libraries take on the burden of working correctly with null in all of these cases.

Another key consideration is performance. Separation is a critical way to configure a parallel pipeline. It was performed sequentially until the work was transferred to different threads, which should be performed in parallel. In Amdahl's Law , to make parallelism as efficient as possible, you want to minimize the overhead of sequential tuning.

The fact is that Optional is a field, and there is a boxing value and an unboxing value in and out of Optional . The JIT compiler may optimize it in some cases, but it may not be. Even so, there is a period of time when the code works, but Optional is not yet optimized. This is an additional overhead. Since the library code is ready to bear the burden of handling null properly, we can guarantee that there is no overhead for boxing by simply not using Optional at all in this case.

+10
source

Spliterator is part of an internal thread implementation. It should not be used in business logic where Optional would be convenient. Its rather low-level interface, whose main goal is to be fast. Therefore, there is no reason for Optional .

You can argue that Optional can usually be excluded by the JIT compiler. However, this is not always the case. For example, the default maximum query depth for embedding in the Hotspot JIT compiler is 10, and normal stream processing has more stack frames, so even one additional stack frame may prevent optimization.

+7
source

All Articles