Default Stream <E> stream () vs static <T> Stream <T> of (T t)
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 */
source to share
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.
source to share
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.
source to share
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.
source to share