Java Reference
In-Depth Information
Finally, if you want to get particularly fancy and highly efficient about things, you can use the Collector
part of the Stream API. The Collector part of the Stream API provides a kind of specialized reduce logic,
where the result is a composite of the existing elements. Many examples of Collector implementations can
be found in the
java.util.stream.Collectors
class. Among these are
Collectors.toList()
,
Collectors.
toSet()
, and
Collectors.toCollection(Supplier)
. Each of those methods returns a Collector instance,
and that is passed to
stream.collect(Collector)
. Both
Collectors.toList()
and
Collectors.toSet()
do exactly what they sound like: they return a
List
or
Set
. However, there is no guarantee given about the
extent of the mutability of the resulting collection, nor its serializability, nor its thread safety. If you want
to be more specific about what you are getting back, you call
Collectors.toCollection(Supplier)
. The
Supplier
is responsible for supplying collections of the type you want, and it is presumed that each time the
supplier is called, it will supply a new instance. Because of that, the simplest thing to pass as a supplier is
the constructor itself, such as
CopyOnWriteArrayList::new
. This results in code that looks like Listing 7-10,
which is both terse and highly performant.
Listing 7-10.
Bridging Streams to Collections Using a Collector
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;
public class Listing10 {
public static Stream<Integer> generateParallelStream() {
final int elements = 1000;
List<Integer> toReturn = new ArrayList<>(elements);
for (int i = 0; i < elements; i++) {
toReturn.add(i);
}
return toReturn.parallelStream();
}
public static void main(String[] args) {
// Perform the stream processing
List<Integer> list = generateParallelStream()
.collect(Collectors.toCollection(CopyOnWriteArrayList::new));
}
}
Bridging Arrays and Streams
Going back and forth between arrays and streams is really quite wonderfully simple. To get a stream from
an array, use
Stream.of(array)
. To get an array from a stream, you have two choices: either accept an array
of
Object
instances and call
Stream.toArray()
; or pass that method a way to construct an array of a given
size, and it will return the constructed array. The simplest way to define the supplier is to pass in the array
constructor, such as
Integer[]::new
. Both going into and out of arrays is demonstrated in Listing 7-11.