Как сделать класс итератор для другого класса

Есть класс, расширяющий Iterable<Integer>, по которому мы будем итерироваться.
В процессе итерирования мы будем от него получать случайные числа в диапазоне значений.
Диапазон задаётся двумя числами - минимальным и максимальным значениями. Как создать класс итератор?

public class Randoms implements Iterable<Integer> {       
  
    protected int min, max;

    public Randoms(int min, int max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public Iterator<Integer> iterator() {
        // ???
    }
}

Ответы (1 шт):

Автор решения: Nowhere Man

Поскольку в первоначальном коде данной реализации интерфейса Iterable было приведено поле-итератор по примитивам int PrimitiveIterator.OfInt, то можно создать и вернуть это поле в качестве требуемого итератора.

Варианты реализации могут отличаться в зависимости от задания.

Например, если данная реализация Iterable<Integer> возвращает бесконечную последовательность, метод hasNext соответствующего итератора должен всегда возвращать true, а метод nextInt может использовать метод соответствующего класса-наследника Random.

Например, существует метод ThreadLocalRandom::nextInt(int origin, int bound), позволяющий получить случайное число в заданном диапазоне.

Тогда полная реализация Randoms может выглядеть так:

class Randoms implements Iterable<Integer> {
    protected ThreadLocalRandom random = ThreadLocalRandom.current();
    protected PrimitiveIterator.OfInt randomIt = new PrimitiveIterator.OfInt() {
        @Override
        public boolean hasNext() {
            return true;
        }
        
        @Override
        public int nextInt() {
            return random.nextInt(min, max);
        }
    };
    protected int min, max;

    public Randoms(int min, int max) {
        this.min = min;
        this.max = max + 1; // чтобы включить `max` в диапазон
    }
    
    @Override
    public Iterator<Integer> iterator() {
        return randomIt;
    }
}

Также хотел бы обратить внимание, что для того, чтобы сгенерировать последовательность случайных чисел, совершенно не обязательно писать свои реализации Iterable / Iterator / PrimitiveIterator.

В классе Random и его наследниках есть методы, возвращающие стримы случайных целых чисел IntStream в заданном диапазоне:

Таким образом, получить бесконечные последовательности случайных чисел в заданном диапазоне (например, [10, 40]) можно по-разному:

Iterable<Integer> myRandoms = new Randoms(10, 40);   // 40 inclusive
IntStream streamRandoms = new Random().ints(10, 41); // 40 exclusive, adding 1
→ Ссылка