Java Reference
In-Depth Information
Listing 7-11. Bridging Arrays and Streams
import java.util.stream.*;
public class Listing11 {
public static Integer[] generateArray() {
final Integer[] elements = new Integer[1000];
for (int i = 0; i < elements.length; i++) {
elements[i] = i;
}
return elements;
}
public static void main(String[] args) {
Integer[] array = generateArray();
Stream<Integer> stream = Stream.of(array);
array = stream.toArray(Integer[]::new);
}
}
Making Interfaces More Lambda Friendly
Many of the interfaces in the Java SDK only have one non-default method on them. This is true of Runnable ,
Callable , AutoCloseable , and many of the other most common interfaces. These interfaces can be
implemented directly using a lambda by simply using the lambda where the interface is expected. We
have seen this trick regularly in our code, most recently in Listing 7-5, where we returned a lambda as our
implementation of ResourceExceptionHandler.FunctionWithResource in generateMap() . So those
single-method interfaces work quite nicely with lambdas already. Most of the remaining interfaces are very
large, such as Collection , and clearly out of reach of a single lambda as its entire implementation.
However, there are a small number of interfaces in the SDK - and quite a few in user code - which have
only a few non-default methods, and you might really want to be able to define its implementation inline
through lambdas. This is a very useful trick, but you can't define more than one method at a time using a
lambda, and we need to define multiple methods at the same time. How do we do it?
This is where some serious creativity comes in. The trick is to define a new single method that can
be used to drive the implementation of all the other methods. The user then specifies that new method,
and our code will delegate to that new method's implementation. This new method and the delegating
implementations go into a new interface that extends our target interface.
For instance, let's say that we wanted to create an Iterator that you could define with a lambda.
There are two non-default methods on Iterator : hasNext() and next() . Both have to do with the next
element, but the former tests for existence without advancing while the latter advances. Therefore, our single
method will need to operate in both an advancing and non-advancing mode. Since hasNext also may look
beyond the end of the iterator, where there are no elements, our single method will need to return its result
optionally. The result is this method:
Optional<E> maybeNext(boolean advance);
 
Search WWH ::




Custom Search