Можно ли безопасно отключить ListIterator для Iterator? (Реализация оболочки CopyOnWrite для List)

У меня есть много примеров в коде, где Collection, чаще всего List, возвращается из метода, и для учета вызывающего абонента, возможно, изменяющего этот список, создается защитная копия.

JDK, похоже, не предоставляет оболочку для этой цели, поэтому я пытаюсь свернуть свою собственную (Примечание: java.util.concurrent.CopyOnWriteArrayList - это не то, что я ищу здесь).

Схематично я пытаюсь:

public class CopyOnWriteList<E> extends List<E> {

    protected List<E> list;
    protected boolean isCopied;

    public CopyOnWriteList(List<E> list) {
        this.list = list;
    }

    private void ensureCopy() {
        if (!isCopied) {
            list = new ArrayList<E>(list);
            isCopied = true;
        }
    }

    public E get(int i) {
        return list.get(i);
    }

    public boolean add(E e) {
        ensureCopy();
        return list.add(e);
    }

    // ... many more simple methods

}

Для большей части API это достаточно просто, но, посмотрев на java.util.ArrayList, я обнаружил, что для метода iterator () он возвращает другую реализацию, чем для listIterator (), хотя ListIterator расширяет свой Iterator и не добавляет новых участников.

Интересно, есть ли за этим более глубокая причина - я планировал просто реализовать iterator () и listIterator (), все возвращающие один и тот же тип итератора - ListIterator. Есть ли какая-то логическая причина, по которой нельзя не возвращать ListIterator из метода iterator ()?


person Durandal    schedule 23.11.2013    source источник


Ответы (1)


ListIterator расширяет Iterator. Поэтому, если вы возвращаете объект, реализующий ListIterator, он, очевидно, также реализует Iterator. Но вы также можете решить вернуть другой объект, который реализует только Iterator, потому что реализация может быть более эффективной. Решение остается за вами.

person epinuj    schedule 23.11.2013
comment
Что ж, это очевидно. Вопрос в том, конкретно, почему бы не возвращать ListIterator из iterator (), как это сделано в java.util.ArrayList. И это не оптимизированная реализация - я проверил реализацию. Итак, почему они реализовали это таким образом - есть ли разумная причина для этого. - person Durandal; 26.11.2013
comment
Какая реализация? В OpenJDK это разные реализации для Iterator и ListIterator. Что касается вопроса, почему они реализовали это таким образом, они сделали это потому, что могли, и у них могло быть множество причин для этого. И это приятный подход ООП - как пользователь API вы получите объект, который соответствует контракту, указанному в интерфейсе, и вас не должно беспокоить его реальная реализация :) - person epinuj; 05.12.2013