简体   繁体   中英

Why overload the varargs method of() in Java Stream interface?

The Stream interface has two overloads for the method of() . One of these is a variable-arity method while the other takes a single argument.

Is the single-argument method a performance optimization versus passing one argument to the variable-arity method? If so, how does it improve performance? The same questions could be asked of the empty() method, which would seem to be syntax sugar around the variable-arity of() .

I see that the implementation differs between these methods, with the difference apparently being how the Spliterator is instantiated; but what advantage does this offer to the Stream API?

Empty stream and single element stream are very common use-cases, especially when you utilize the .flatMap() . For example, here's how Optional.stream() is implemented in Java-9:

public Stream<T> stream() {
    if (!isPresent()) {
        return Stream.empty();
    } else {
        return Stream.of(value);
    }
}

So given the stream of Optionals you can unwrap them into the flat stream this way:

streamOfOptionals.flatMap(Optional::stream);

Here you create tons of empty streams as well as single element streams, so optimizing such cases looks very reasonable. In particular, Stream.empty() unlike Stream.of() does not create an empty array and does not create the spliterator (it reuses the same spliterator instance). Stream.of(T) is also particularly optimized inside the StreamBuilderImpl , so no array is allocated for single element.

Yes, it's an optimization to avoid the overhead of creating an array to hold only a single element, which is what you'd get if you used the varargs version.

The same questions could be asked of the empty() method, which would seem to be syntax sugar around the variable-arity of()

What implementation version are you looking at? When I look at the implementation I don't see this.

I've stumbled across an official resource which confirms previous answers to this question: JEP 269: Convenience Factory Methods for Collections . The description of that proposal is to,

Provide static factory methods on the List , Set , and Map interfaces for creating unmodifiable instances of those collections.

These will include varargs overloads, so that there is no fixed limit on the collection size... Special-case APIs (fixed-argument overloads) for up to ten of elements will be provided. While this introduces some clutter in the API, it avoids array allocation, initialization, and garbage collection overhead that is incurred by varargs calls.

So the performance optimization is quite simply to avoid the array of a varargs method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM