Java Reference
In-Depth Information
With that method in hand, we can define the other two methods in the iterator using default methods.
For next() , we call maybeNext and pass in true to advance. We get back an Optional result, and we use the
Optional API to either return its contained value or throw a NoSuchElement exception. For hasNext() , we call
maybeNext and pass in false to avoid advancing. Then we simply let the caller know if the result is present.
All of this goes into our new interface, which extends Iterator . Now users can assign the lambda into this
type in order to get an Iterator out. This code, and a demonstration of how it works, is in Listing 7-12.
Listing 7-12. Making Iterator More Lambda Friendly
import java.util.*;
import java.util.concurrent.atomic.*;
public class Listing12 {
public interface LambdaIterator<E> extends Iterator<E> {
Optional<E> maybeNext(boolean advance);
default E next() {
return maybeNext(true).orElseThrow(NoSuchElementException::new);
}
default boolean hasNext() {
return maybeNext(false).isPresent();
}
}
public static Iterator<String> generateIterator() {
String[] values = new String[]{"Hello", " ", "World"};
AtomicInteger nextI = new AtomicInteger(0);
LambdaIterator<String> it = advance -> {
if (nextI.get() >= values.length) return Optional.empty();
String result = values[nextI.get()];
if (advance) nextI.incrementAndGet();
return Optional.of(result);
};
return it;
}
public static void main(String[] args) {
Iterator<String> it = generateIterator();
}
}
The big trick with this approach is that you have to come up with the clever single method that can
handle all the needs of any given method. Your super-method does have access to the other methods in
the interface, but if you use those other methods, then you need to be extremely careful not to produce a
recursive loop. Coming up with a good, single method is the kind of problem that should excite you as a
developer.
Search WWH ::




Custom Search