Как реализовать пользовательский итератор для многомерного массива в Java?

#java #arrays #multidimensional-array #iterator

#java #массивы #многомерный массив #Итератор

Вопрос:

В настоящее время я пытаюсь настроить пользовательский метод итератора для двумерного массива.

Например. если массив является {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}} , next() метод должен возвращать последовательно при каждом вызове 1, 2, 3, 4, 5, 6, 7, 8, 9.

Моя идея была примерно такой:

 public Iterator<Type> iterator() {
    return new Iterator<Type>() {
        private int currentRow = 0;
        private int currentColumn = 0;

        public boolean hasNext() {
            return currentRow < array.length;
        }

        public Type next() {
            if(currentColumn   1 == array[0].length){
                currentColumn = 0;
                currentRow   ;
            }
            return array[currentRow][currentColumn  ];
        }
    }
}
  

Но он не выводит элементы в правильном порядке, а иногда даже возвращает null.

Комментарии:

1. Убедитесь, что массив содержит то, что вы думаете, что он содержит. Либо посмотрите на это в отладчике, либо запишите это в стандартный вывод, используя другую итерацию. Кроме того, взгляните на контракт для Iterator. Ваш следующий метод должен выдавать ошибку NoSuchElementException , если он вызывается, когда следующего элемента нет. Кроме того, для надежности и общности рассмотрите возможность проверки, array[currentRow].length а не array[0].length .

2. Метод deepToString класса Arrays отформатирует 2D-массив для печати. hasNext также должен проверять значение currentColumn

Ответ №1:

Одно из возможных решений:

 public Iterator<Type> iterator() {
    return new Iterator<Type>() {
        private int currentRow = 0;
        private int currentColumn = 0;

        public boolean hasNext() {
            if (currentRow   1 == array.length) {
                return currentColumn < array[currentRow].length;
            }
            return currentRow < array.length;
        }

        public Type next() {
            if (currentColumn == array[currentRow].length) {
                currentColumn = 0;
                currentRow  ;
            }
            if (currentRow == array.length -1 amp;amp; currentColumn == array[currentRow].length - 1) {
                throw new NoSuchElementException();
            }
            return array[currentRow][currentColumn  ];
        }
    };
}
  

В качестве альтернативы вы можете использовать Java Streams:

 public Iterator<Type> iterator() {
    return Arrays.stream(array)
            .flatMap(Arrays::stream)
            .iterator();
}
  

Для целых чисел это будет выглядеть следующим образом:

 public Iterator<Integer> iterator() {
    return Arrays.stream(array)
            .map(Arrays::stream)
            .flatMap(IntStream::boxed)
            .iterator();
}