Написание универсального итератора на Java

avatar
Szmagpie
7 апреля 2018 в 23:39
1932
1
1

У меня заканчивались исключения из памяти, когда я сохранял коллекцию моего класса AbstractState в памяти, поэтому я пытаюсь написать итерируемый/итератор. У меня есть небольшие знания C#, но небольшой опыт работы с Java. В C# я бы написал метод, возвращающий IEnumerable<AbstractState>, но здесь это не кажется таким простым.

AbstractState хранит пару координат, хотя в зависимости от реализации операции над ними различаются. (Он также расширяет общий MyPair<Coordinate>.)

В пределах AbstractState я определяю конструктор AbstractState(Coordinate A, Coordinate B){super(A,B);}. Я переопределяю это в некоторых, но не во всех подклассах. Coordinate — бетон. Вот моя итерация:

import java.util.Iterator;

public class StateSpace<T extends AbstractState> implements Iterable<T> {
    @Override
    public Iterator<T> iterator() {
        return new StateIterator();
    }
}

и мой итератор:

public class StateIterator<T extends AbstractState> implements Iterator<T> {
    private Iterator<Coordinate> iX, iY;

    StateIterator(){
        iX = Main.GRID.iterator();
        iY = Main.GRID.iterator();
    }

    @Override
    public boolean hasNext() {
        return iX.hasNext() || iY.hasNext();
    }

    @Override
    public T next() {
        return null;
    }
}

(GRID здесь статический диапазон Coordinateс.)

Как правильно реализовать метод next()? (Или, какой дизайн моего кода лучше подходит для решения этой проблемы?)


Создание экземпляра T не работает, и я не могу создать экземпляр абстрактного класса. Я думаю, что был близок, пытаясь

getDeclaredConstructor(Coordinate.class, Coordinate.class).newInstance(iX.next(), iY.next());

но я получил предупреждение компилятора об отсутствии такого метода.

У меня были непроверенные приведения, когда я применял к T, так что подозреваю, что это плохая идея. Наличие большого количества итераторов/итерируемых объектов непривлекательно, так как я проверял бы (через операторы if или switch), какой итератор мне нужен, что подрывает структуру моего объектно-ориентированного кода.

Принимаются любые предложения, спасибо

Источник
inor
9 апреля 2018 в 05:58
0

что вы подразумеваете под «когда я сохранил коллекцию своего класса AbstractState в памяти»? Пожалуйста, уточните: у вас уже есть коллекция AbstractState в памяти, и вы получаете исключение памяти при добавлении к ней? в этом случае повторение вам не поможет.

Szmagpie
13 апреля 2018 в 14:39
0

@inor извините - только что увидел это. Ранее я создал коллекцию AbstractState для последующего использования (в циклах for). Я даже не мог его создать, потому что он был слишком большим. Итак, я хотел бы выполнить итерацию по итерируемому объекту, чтобы не нужно было хранить каждый AbstractState в памяти.

Ответы (1)

avatar
K.Nicholas
7 апреля 2018 в 23:57
1

Передать this конструктору итератора. StateSpace имеет доступ к экземпляру типа T, поэтому он может реализовать методы для определения того, как getNext() и hasNext(). Непонятно, о чем iX и iY.

import java.util.Iterator;

public class StateSpace<T extends AbstractState> implements Iterable<T> {
    List<T> types;
    int pos;

    public StateSpace() {
        types = new ArrayList<>();
    }
    public void add(T type) {
        types.add(type);
    }
    T getNext() {
        return types.get(pos++);
    }
    boolean hasNext() {
         return pos < types.size()-1;
    }
    @Override
    public Iterator<T> iterator() {
        return new StateIterator(this);
    }
}

и

public class StateIterator<T extends AbstractState> implements Iterator<T> {
    private Iterator<Coordinate> iX, iY;
    private StateSpace<T> stateSpace;

    StateIterator(StateSpace<T> stateSpace){
        this.stateSpace = stateSpace;
        iX = Main.GRID.iterator();
        iY = Main.GRID.iterator();
    }

    @Override
    public boolean hasNext() {
        return iX.hasNext() || iY.hasNext();
    }

    @Override
    public T next() {
        return stateSpace.getNext(); // or whatever.
    }
}

может поможет.

Szmagpie
8 апреля 2018 в 00:10
0

Спасибо за ответ. next() должен возвращать T, но stateSpace имеет тип StateSpace<T>. Я попытался поместить метод в StateSpace, который возвращает T, но у меня те же проблемы

K.Nicholas
8 апреля 2018 в 00:19
0

Хорошо, извините, если StateSpace сохраняет или имеет доступ к типу T, тогда stateSpace должен иметь возможность getNext(); Обновлено.

Szmagpie
8 апреля 2018 в 00:45
1

Ага, в этом есть смысл: если вы не можете получитьNext, то на самом деле это не «Итерируемый». Мне нужно отслеживать текущий объект AbstractSpace, чтобы я мог перейти к следующему