The Stream.Builder<T> builder() static method returns an internal (located inside the interface Stream interface) Builder interface that can be used to construct a Stream object. The Builder interface extends the Consumer interface, and has the following methods:
- void accept(T t): Adds an element to the stream (this method comes from the Consumer interface).
- default Stream.Builder<T> add(T t): Calls the accept(T) method and returns this, thus allowing chaining add(T) methods in a fluent, dot-connected style.
- Stream<T> build(): Transitions this builder from the constructing state to the built state. After this method is called, no new elements can be added to the stream.
Using the add() method is straightforward:
Stream.<String>builder().add("cat").add(" dog").add(" bear")
.build().forEach(System.out::print); //prints: cat dog bear
Just notice the <String> generics that we have added in front of the builder() method. This way, we tell the builder that the stream we are creating will have String type elements. Otherwise, it will add them as Object types.
The accept() method is used when the builder is passed as a parameter of the Consumer type, or when you do not need to chain the methods that add the elements. For example, here is how the builder is passed in as a Consumer object:
Stream.Builder<String> builder = Stream.builder();
List.of("1", "2", "3").stream().forEach(builder);
builder.build().forEach(System.out::print); //prints: 123
There are also cases where there is no need to chain the methods while adding the stream elements. The following method receives a list of String objects, and adds some of them (those that contain the character a) to a stream:
Stream<String> buildStream(List<String> values){
Stream.Builder<String> builder = Stream.builder();
for(String s: values){
if(s.contains("a")){
builder.accept(s);
}
}
return builder.build();
}
Notice that we have added the <String> generics the Stream.Builder interface for the same reason—to tell the builder that the elements we are adding should be treated as String types.
When the preceding method is called, it produces the expected result:
List<String> list = List.of("cat", " dog", " bear");
buildStream(list).forEach(System.out::print); //prints: cat bear