Вы можете использовать функцию для абстрагирования последовательных значений и предиката для управления окончанием итерации, в конечном итоге создавая реализацию Развернуть :
public final class UnfoldIterator<E> implements Iterator<E> {
public static <E> Iterator<E> unfold(E initial, Function<? super E, ? extends E> next, Predicate<? super E> finished) {
return new UnfoldIterator<E>(initial, next, finished)
}
private final Function<? super E, ? extends E> next;
private final Predicate<? super E> finished;
private E element;
public UnfoldIterator(E initial, Function<? super E, ? extends E> next, Predicate<? super E> finished) {
super();
this.next = next;
this.finished = finished;
this.element = initial;
}
@Override protected Integer computeNext() {
if (finished.apply(element)) {
return endOfData();
}
E result = element;
element = next.apply(element);
return result;
}
}
Тогда ArithmeticSeries становится:
public Iterable<Integer> series(final int start, final int step, final int stop) {
return new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new UnfoldIterator<Integer>(start, new Function<Integer, Integer>() {
public Integer apply(Integer from) {
return from - step;
}
}, new Predicate<Integer>() {
public boolean apply(Integer input) {
return input >= stop;
}
});
}
};
}
Конечно, код сейчас кажется более сложным, но с соответствующими базовыми функциями для сравнения и алгебры вызов становится намного понятнее:
return unfold(start, subtractBy(step), not(lessThan(stop)));