Java Reference
In-Depth Information
Listing 5-5. Using a Stream Builder to Convert a ResultSet to a Stream
public static Stream<WordUsage> createStream(ResultSet rs)
throws SQLException
Stream.Builder<WordUsage> builder = Stream.builder();
while ( {
WordUsage usage = WordUsage.fromResultSet(rs);
The primary advantage of this approach is that it is very familiar to Java developers. This is your
standard way of building up a collection. Its next major advantage is that the stream built by the stream
builder is extremely flexible, allowing parallel execution and other behind-the-scenes optimizations. Finally,
this approach also makes reasoning about the ResultSet and the stream very easy: you know that there will
not be a data access or data conversion error once this method returns, and the result set (and its resources)
can be closed with the method returns.
The primary disadvantage of this approach is that it is a resource hog. It hogs the thread of execution,
preventing anything else from being done by that thread until all the results are read. It also hogs memory,
because the entire stream has to be buffered into memory before any of it can be processed. Both of these
disadvantages are minor if the data set is small, and they get more serious as the data set becomes larger.
With even a moderately large data set (such as ours), this is not a good fit. With a smaller data set, however,
the simplicity of the approach might well outweigh its inefficiencies.
Method Two: Building a Stream Using Stream.of and Stream.flatMap
When we are looking to move from a ResultSet to a Stream, our problem is that we have trouble getting into
the Stream API. This approach gets into the Stream API by constructing a single-element stream holding just
the ResultSet. We will then use the Stream.flatMap method that we saw last chapter to explode the ResultSet
into the resulting objects.
In this approach, the stream consisting of a single element will be constructed through Stream.
of(resultSet) . The Stream.of method takes any number of arguments, and will construct a highly efficient
stream containing those elements in argument order. Unlike the Stream.Builder approach, where objects
can be determined and passed in at run time after the builder is initiated, the elements of Stream.of all need
to be provided immediately at the point when the method is invoked.
To convert the stream from a single ResultSet into the mapped elements, we will use Stream.flatMap .
As we saw in the last chapter, this allows each element of the source stream to be mapped into zero or more
elements of the result stream. In our case, the single ResultSet element of the source stream is mapped into
one WordUsage element for each row of the ResultSet.
The catch we have here is that we will need to leave the ResultSet open until all the rows are processed.
In order to close the ResultSet at the appropriate time, we can use Stream.onClose(Runnable) . This
method allows you to hook a callback to be executed when the stream is closed. It is not often used, but it
does enable you to delegate responsibility for resource management to stream itself. This is very useful for
keeping your code clean and not threading resources through calls in your codebase.
The one catch with using Stream.onClose(Runnable) is that you need to use the returned Stream .
Some Java developers will register the handler with onClose and presume that the stream instance itself has
been modified. This may, in fact, be the case. However, the Stream API allows the stream implementation
to return an entirely new instance with the handler attached, and so you want to be sure that you use that
returned instance.
Search WWH ::

Custom Search