java Iterator для многомерного массива

188
30 октября 2018, 03:50

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

Ввод:

int[][] arr = {{1, 2, 3}, {4, 5}};

Вывод:

1
2
3
4
5

Предполагаю, что сделать 2 итератора по столбцу и строке.

public class MatrixIterator implements Iterator {
private int[][] values;
private int rowIndex = 0;
private int colIndex = 0;
private Iterator<Integer> rowIterator;
private Iterator<Integer> colIterator;

public MatrixIterator(int[][] values) {
    this.values = values;
    rowIterator = new Iterator<Integer>() {
        @Override
        public boolean hasNext() {
            return values.length > rowIndex;
        }
        @Override
        public Integer next() {
            return values[rowIndex++][colIndex];
        }
    };
    colIterator = new Iterator<Integer>() {
        @Override
        public boolean hasNext() {
            return values[rowIndex].length > colIndex;
        }
        @Override
        public Integer next() {
            return values[rowIndex][colIndex++];
        }
    };
}
@Override
public boolean hasNext() {
    if (rowIterator.hasNext() && colIterator.hasNext()) {
        return true;
    } else {
        return false;
    }
}
@Override
public Object next() {
    if (rowIterator.hasNext()) {
        if(colIterator.hasNext()){
            return values[rowIndex][colIndex++];
        }
        else {
            colIndex =0;
            return values[rowIndex++][colIndex];
        }
    }
    else return null;
}
}

Тогда как правильно реализовать методы основного класса?

Answer 1

Для последовательного обхода элементов можно сделать так:

public class  MatrixIterator<T> implements Iterator<T>{
    private int size;          //всего элементов в матрице 
    private int position = 0;  //номер текущего элемента для "выдачи"
    private int row = 0;       //строка текущего элемента
    private int col = 0;       //столбец текущего элемента
    private T[][] matrix;
    public MatrixIterator(T[][] matrix) {
        this.matrix = matrix;
        this.size = countElements(matrix);
    }
    private int countElements(T[][] matrix) {  //считаем количество элементов в матрице
        int count = 0;
        for (T[] row : matrix) {
            count += row.length;
        }
        return count;
    }
    @Override
    public boolean hasNext() {
        return position < size;
    }
    @Override
    public T next() {
        if (position >= size) { //если перебрали все элементы, то бросить исключение
           throw new NoSuchElementException();
        } 
        T element = matrix[row][col];  //запоминаем текущий элемент
        //переходим к следующему элементу
        position++;
        col++;
        while (row < matrix.length && col >= matrix[row].length) { //для того, чтоб пропустить возможные "пустые" строки
            col = 0;
            row++;
        }
        return element;
    }
}

В данном случае итератор параметризирован, так что не имеет значения с матрицей какого типа работать. В row и col сохраняется позиция текущего элемента, который необходимо вернуть. Цикл while для того, чтоб пропустить возможные пустые строки (например, {{1, 2, 3}, {}, {4, 5}, {6}}). Использовать итератор можно следующим образом

Integer[][] matrix = {{1, 2, 3}, {}, {4, 5}, {6}};
Iterator<Integer> iterator = new MatrixIterator<>(matrix);
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

Вывод:

1
2
3
4
5
6
Answer 2

Можно попробовать внутри hasNext() итерироваться по массиву с помощью forEach и выдавать нужный объект.

    private class ElementsIterator implements Iterator<T> {
    T[][] value;
    private int cursor = 0;

    @Override
    public boolean hasNext() {
        return cursor != size;
    }
    @Override
    public T next() {
        //Равен нулю каждый раз при входе в метод.
        int nextCursor = 0;
        for (T x[]: value) {
            for (T y : x) {
                //сброшенный nextCursor поднимается
                //до уровня текущей позиции cursor
                //и отдает нужный элемент.
                if (nextCursor++ == cursor) {
                    cursor++;
                    return y;
                }
            }
        }
        //Если перед вызовом next()
        //проверять есть ли элементы,
        //то сюда у нас программа не дойдет.
        throw new NoSuchElementException();
    }
}
Answer 3

Другой вариант:

public class IteratorFor2DArray implements Iterator {
    private int[][] data;
    private int i, j;
    public IteratorFor2DArray(int[][] data) {
        this.data = data;
    }
    @Override
    public Integer next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        int element = data[i][j];
        j++;
        while (i < data.length && j >= data[i].length) {
            j = 0;
            i++;
        }
        return element;
    }
    @Override
    public boolean hasNext() {
        return (i < data.length && j < data[i].length);
    }
} 
READ ALSO
Не хочет работать hibernate под Tomcat

Не хочет работать hibernate под Tomcat

Когда выполнение кода метода doGet сервлета доходит до момента обращения к базе через hibernate в логе появляется нижеуказанная ошибка и останавливается...

187
Передача параметров в jsp

Передача параметров в jsp

Есть файл jsp поставляется в библиотеке, менять не могу, но мне нужно передать параметр в этот jspGри передаче тегом param переменная text появляется...

216
Преобразовать результат сложения Double

Преобразовать результат сложения Double

Подскажите пожалуйста, почему результат сложения получается "10E-7", а не "0

178
Из-за @JsonFormat теряется один день

Из-за @JsonFormat теряется один день

В своем проекте использую библиотеку Jackson для сериализации объектов в JSONПри использовании @JsonFormat устанавливается дата на один день раньше

214