Отказоустойчивый итератор для стека

Я хочу реализовать Fail-Fast Iterator для удаления записей из моего собственного списка и проверки его правильного поведения. Список содержит элементы типа MyEntry.

Эти записи содержат общее значение и ссылку на следующую запись.

class MyEntry<E>  {

    MyEntry<E> next;
    E o;

    MyEntry() {
        this(null, null);
    }

    MyEntry(E o) {
        this(o, null);
    }

    MyEntry(E o, MyEntry<E> e) {
        this.o = o;
        this.next = e;
    }
}

Сам список отслеживает свою позицию с помощью записи pos и ведет себя как стек. Теперь я хотел бы реализовать отказоустойчивый итератор, который позволяет мне перебирать список и удалять записи вместо того, чтобы вызывать исключение UnsupportedOperation Exception.

import java.util.Iterator;
import java.util.NoSuchElementException;

public class MyList<E> implements Cloneable, java.lang.Iterable {

    private MyEntry<E> begin;

    private MyEntry<E> pos;


    public MyList() {
        pos = begin = new MyEntry<E>();
    }


    public boolean empty() {
        return begin.next == null;
    }


    public boolean endpos() { 
        return pos.next == null;
    }


    public void reset() {
        pos = begin;
    }

    /**
     * Advances one step in this List.
     *
     * @throws NoSuchElementException if the last Entry of this List already has been reached.
     */
    public void advance() {
        if (endpos()) {
            throw new NoSuchElementException("Already at the end of this List");
        }
        pos = pos.next;
    }

    /**
     * Returns the actual element of this List.
     *
     * @return the actual element
     * @throws RuntimeException if the last Entry of this List already has been reached.
     */
    public E elem() {
        if (endpos()) {
            throw new NoSuchElementException("Already at the end of this List");
        }
        return pos.next.o;
    }

    /**
     * Inserts <code>o</code> in this List. It will be placed before the actual
     * element. After insertion the inserted element will become the actual
     * element.
     *
     * @param x the element to be inserted
     */
    public void add(E x) {
        MyEntry<E> newone = new MyEntry<E>(x, pos.next);

        pos.next = newone;
    }

    /**
     * Deletes the actual element of this List. The element after the actual
     * element will become the new actual element.
     *
     * @throws NoSuchElementException if the last Entry of this List already has been reached.
     */
    public void delete() {
        if (endpos()) {
            throw new NoSuchElementException("Already at the end of this List");
        }
        pos.next = pos.next.next;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            private MyEntry<E> it = null;

            @Override
            public boolean hasNext() {
                return pos != null;
            }
            @Override
            public E next() {
                if (it==null)
                    it = begin;
                else
                    it = it.next;
                return it.o;
            }
            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

}

Я также уже пытался реализовать Iterator в моем списке и тестировал его с помощью моего тестового класса.

public class MyListTest {

@Test
public void test() {

    MyList list = new MyList();

    list.add("a");
    list.add("b");
    list.add("c");

    while(list.iterator().hasNext()==true) {
        System.out.println(list);
    }

    list.iterator().remove();

    while(list.iterator().hasNext()==true) {
        System.out.println(list);
    }
}

}

Но вывод зацикливается на c и даже не может удалить Entry.

Теперь я застрял в правильной реализации итератора Fast-Fail Iterator, который может перебирать MyList и удалять записи. Поскольку я не мог разбить это на одну проблему, я составил список из нескольких вопросов, которые возникли, когда я пытался реализовать Iterator.

  • Должен ли Iterator быть реализован в классе MyList или он должен быть реализован в собственном классе?
  • Как мне заставить итератор продвигаться по MyList, как это сделал метод advance ()?
  • Удобен ли цикл while в тестовом классе или вместо него следует использовать другой метод?

Я не понимаю, что означает это предложение: «Но вывод зацикливается на c и даже не может удалить запись». Какую именно ошибку вы видите, пожалуйста?

markspace 03.06.2018 20:21

Фактического сообщения об ошибке во время выполнения нет, все, что печатается на консоли, - это c, и мне нужно остановить виртуальную машину вручную, иначе она продолжит печатать c. Я предполагаю, что это потому, что Iterator проверяет, есть ли следующая запись, и распечатывает c, но он не продвигается в списке

Trikalium 03.06.2018 20:34
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
65
0

Другие вопросы по теме