Ленивый пример c итераторами

Код на потестить, с лекции, с ленивыми функциями

public class Main {

    // базовый интерфейс для ленивых иетраторов
    interface SFn<T> extends Iterable<T> {
        /*
         * Функция для отображения одного итератора в другой
         */
        default <R> SFn<R> map(Function<T, R> func) {
            Iterator<T> baseIterator = this.iterator();
            return () -> new Iterator<R>() {
                public boolean hasNext() {
                    // новый итератор синхронизирован с базовым
                    // и двигается синхронно с ним
                    return baseIterator.hasNext();
                }

                public R next() {
                    // очередное значение итератора считается
                    // путем применения функции func к значению базового итератора
                    return func.apply(baseIterator.next());
                }
            };
        }

        /*
         * Функция для фильтрации данных итератора
         * на вход принимает булеву функцию
         * которая вохвращает true если значение подходит и false если не подходит
         */
        default SFn<T> filter(Function<T, Boolean> func) {
            Iterator<T> baseIterator = this.iterator(); // выковыриваем базовый итератор
            return () -> new Iterator<T>() {
                T currentValue; // для хранения текущего значения итератора

                public boolean hasNext() {
                    // сдвиг нового итератора не синхронен с базой
                    boolean hasNext = baseIterator.hasNext(); // проверяем есть ли вообще значения в базе
                    if (hasNext) { // если есть
                        do {
                            T value = baseIterator.next(); // вытаскиваем очередное значение базы
                            if (func.apply(value)) { // проверяем выдает ли для него func значение true
                                currentValue = value; // если да, то фиксируем это значение
                                return true; // и возвращаем true, что означает что у нового итератора есть значения
                            }
                        } while (baseIterator.hasNext()); // иначе сдвигаем базу вправо
                    }
                    return false; // если ничего не нашли
                }

                public T next() {
                    // если сюда попали, значит hasNext нового итератора
                    // нашел очередное значение базы удволетворяюще func
                    // в hasNext мы его зафиксировали
                    return currentValue; // а тут возвращаем
                }
            };
        }
    }

    // обертка над списком
    public static class SFnList<T> implements SFn<T> {
        ArrayList<T> list;

        public SFnList(ArrayList<T> list) {
            this.list = list; // пробрасываем список внутрь класса
        }

        public Iterator<T> iterator() {
            // пробрасываем итератор внутренего списка во вне
            return list.iterator();
        }
    }


    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);

        SFnList<Integer> fnList = new SFnList<>(list);

        /*
         * оставляем из списка только значения больше 5
         * и заменяем их на чет/нечет в зависимости от остатка от деления
         * 
         * останутся только значения 6,7,8,9
         * которые привратятся в [чет,нечет,чет,нечет]
         */
        for (String s : fnList.filter(x -> x > 5).map(x -> x % 2 == 0 ? "чет" : "нечет")) {
            System.out.println(s);
        }
    }
}