Default Stream <E> stream () vs static <T> Stream <T> of (T t)

default Stream<E> stream()

added to the interface Collection

for supporting streams in Java 8. Similar functionality is supported public static<T> Stream<T> of(T t)

in the class Stream

. What other purpose is static for method () solution?

+3


source to share


4 answers


An stream()

interface method Collection

can be called on an existing collection. As an interface, it can be overridden by actual collection implementations to return Stream

tailored to a specific type of collection.

The JRE standard collections do not take advantage of this feature because the default implementation strategy for delegation spliterator()

, which is also an overridden method, suits their needs. But the documentation even mentions scenarios in which a collection should override stream()

:

This method should be overridden if the spliterator () method cannot return a spliterator that is IMMUTABLE

, CONCURRENT

or late, bind.


In contrast, the static

factory method Stream.of(…)

is for the case where you have a fixed number of items without a specific collection. No need to create a temporary Collection

one when all you need is one Stream

above the items you can list.



Without collections of potentially a different type, there is no need for excessive behavior, so a static

factory method is sufficient .


Note that even if you do not have an enumerable fixed number of items, there is an optimized solution for the problem of creating a single thread if re-assembly is not required:

Stream.Builder<MyType> builder=Stream.builder();
builder.add(A);
if(condition) builder.add(B);
builder.add(C);
builder.build()./* stream operations */

      

+6


source


As far as I can tell, of

this is just a utility method for creating threads on the fly, without having to first wrap the elements inside the collection.

Usually static factory methods are of

provided to skip array creation due to var-args. For example, java-9 immutable collections provide many overloads of these methods, for example:

 Set.of()
 Set.of(E)
 Set.of(E e1, E e2)
 .... so on until 11
 Set.of(E... elem)

      

Even a description of these methods:

While this introduces some confusion to the API, it avoids the overhead of array allocation, initialization, and garbage collection that comes with calls to varargs



Since there are only two methods in Stream:

 Stream.of(T t)
 Streamm.of(T ... values)

      

I believe that small utilities that can create streams from var-args

.

But they still provide a method that creates a Stream with one element (instead of leaving only the var-args method), so this is already optimized for one element.

+3


source


The frontend can add static methods / methods by default since jdk-8. and you can see some examples of applying templates on the interface in this question .

First , they both are called StreamSupport.stream

to create a thread.

// Collection.stream()
default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

// Stream.of(E)
public static<T> Stream<T> of(T t) {
    return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}

      

stream () added to the Collection interface is a good example of using the default Template-Method Pattern . and you can see the source code that the stream method calls the method spliterator

that the default implements in the Collection interface.

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

default Spliterator<E> spliterator() {
    return Spliterators.spliterator(this, 0);
}

      

And the class derived from Collection

can be overridden to spliterator

implement a different algorithm that will use the highest performance algorithm. for example spliterator

in ArrayList

:

public Spliterator<E> spliterator() {
    return new ArrayListSpliterator<>(this, 0, -1, 0);
}

      

Finally , the Stream.of () method is a good example of using a Factory Method in an interface with a static method. it is a factory method for creating a stream from an object instance.

+2


source


Other answers clearly explain the differences between Collection.stream

and Stream.of

when to use one or the other, what design patterns apply, etc. @Holger goes even further and shows a use case Stream.Builder

that I think is heavily underused.

Here I want to complement the other answers by showing the mixed use of methods Stream.of

and Collection.stream

. I hope that this example will be clear enough to show that even if both Stream.of

and Collection.stream

are completely different methods, they can be used together to perform more complex requirements.

Suppose you have lists N

, all of which contain elements of the same type:

List<A> list1 = ...;
List<A> list2 = ...;
...
List<A> listN = ...;

      

And you want to create one stream with the elements of all the lists.

You can create a new empty list and add the elements of all lists to this new list:

int newListSize = list1.size() + list2.size() + ... + listN.size();
List<A> newList = new ArrayList<>(newListSize);

newList.addAll(list1);
newList.addAll(list2);
...
newList.addAll(listN);

      

Then you can call stream()

on that list and you would do:

Stream<A> stream = newList.stream();

      

However, you would create an interim list of meaningless with the sole purpose of streaming initial list of elements list1

, list2

..., listN

.

Much better to use Stream.of

:

Stream<A> stream = Stream.of(list1, list2, ..., listN)
    .flatMap(Collection::stream);

      

First, a stream of lists is created by enumerating each one, and then flat maps this stream of lists to an item stream of all lists using an operation Stream.flatMap

. Thus, Collection.stream

called when the original stream is displayed flat.

+2


source







All Articles