The static Stream.builder() method returns a Stream.Builder object – an implementation of Stream.Builder<T> interface that extends Consumer<T>. It means that the Stream.Builder interface has method void accept(T t) that processes the passed in parameter t. In the case of the Stream.Builder implementation, the passed-in value is added to the internal storage:
Stream.Builder<String> strBuilder = Stream.builder();
strBuilder.accept("abc");
strBuilder.accept("cbd");
The Stream<T> build() method of the Stream.Builder interface creates a Stream objects using the values stored in the internal storage. An attempt to add another value to the builder after the build() method was invoked, triggers an exception. The following is an example of the build() method usage and creating a stream:
List<String> strList = List.of("cat", "dog", "cow");
Stream.Builder<String> strBuilder = Stream.builder();
for(String s: strList){
if(s.contains("o")){
strBuilder.accept(s);
}
}
strBuilder.build()
.forEach(System.out::print); //prints: dogcow
Note the generics specified for the Stream.Builder object. It helps to ensure that the added values are of a certain type, as the programmer intended it to be. If, by mistake, a programmer tries to add to the builder an item of another type, the compiler will warn him about the mismatch.
The Stream.Builder<T> interface has three methods:
— void accept(T t) – adds an element to the stream being built;
— default Stream.Builder<T> add(T t) – adds an element to the stream being built;
— Stream<T> build() – builds the stream, transitioning this builder to the built state.
We have demonstrated the accept() and build() methods and now turn to Stream<T> add(T t). It can be used the same way as the accept(T t) method:
Stream.<String>builder()
.add("a").add("b").add("c").add("d")
.build()
.forEach(System.out::print); //prints: abcd
That’s basically all the builder() method functionality that is used to create a stream.
Similarly, the Stream.Builder can be used for creating numeric streams IntStream, LongStream, and DoubleStream:
IntStream.Builder intBuilder = IntStream.builder();
intBuilder.add(1).add(2);
intBuilder.accept(3);
intBuilder.build().forEach(System.out::print); //prints: 123
LongStream.Builder longBuilder = LongStream.builder();
longBuilder.add(10).add(20);
longBuilder.accept(30);
longBuilder.build().forEach(System.out::print); //prints: 102030
DoubleStream.Builder doubleBuilder = DoubleStream.builder();
doubleBuilder.add(0.1).add(0.2);
doubleBuilder.accept(0.3);
String str = doubleBuilder.build()
.mapToObj(String::valueOf)
.collect(Collectors.joining(", "));
System.out.print(str); //prints: 0.1, 0.2, 0.3
Please, note how, in the last example, we had to convert the stream elements to String (using the mapToObj() operator) to be able to use the collect() operator with the Collectors.joining() collector (we want to print the elements separated by a comma and space).
To be honest, this Collectors.joining() collector is our favorite. In the past, we had to use custom code to build a comma-separated list (and remove the comma after the last element in the resulting string). Now, if we have a list of strings, we just use this collector:
List<String> sList = List.of("cat", "dog", "cow");
String s = sList.stream()
.collect(Collectors.joining(", "));
System.out.print(s); //prints: cat, dog, cow
In the next post, we will talk about creating a stream using method Stream.generate(Supplier s).
See other posts on Java 8 streams and posts on other topics.
You can also use navigation pages for Java stream related blogs:
— Java 8 streams blog titles
— Create stream
— Stream operations
— Stream operation collect()
The source code of all the code examples is here in GitHub.
Send your comments using the link Contact or in response to my newsletter.
If you do not receive the newsletter, subscribe via link Subscribe under Contact.