21

LinkedListがあり、これを何度も繰り返す必要があります。動的に作成されるワークフローの一連のページを追跡するために使用しています。これは私が期待するようには動作しません。この例を考えると:

LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");

ListIterator navigationItr = navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); //Returns page2 again
navigationItr.next(); //Returns page2 again

リストを間違って作成しているか、Iteratorを間違って使用しているのではないかと思いましたが、ドキュメントを読んだ後、これは仕様によるもののようです。

ListIteratorには現在の要素がありません。そのカーソル位置は常に、previous()の呼び出しによって返される要素とnext()の呼び出しによって返される要素の間にあります。

と:

(次へ)リスト内の次の要素を返します。このメソッドは、リストを反復処理するために繰り返し呼び出される場合もあれば、previousへの呼び出しと混合して前後に移動する場合もあります。(nextとpreviousを交互に呼び出すと、同じ要素が繰り返し返されることに注意してください。)

したがって、これを読んだ後、私のコードがそのように動作している理由は明らかです。なぜこのように機能するのか理解できません。この実装に対応するために、removeでさえ後方に曲がっているようです。

remove()メソッドとset(Object)メソッドは、カーソル位置に関して定義されていないことに注意してください。これらは、next()またはprevious()の呼び出しによって返された最後の要素を操作するように定義されています。

概念的には、LinkedListは私のワークフローのケースをかなりうまくモデル化しているように見えましたが、このように動作するIteratorを使用することはできません。ここで何かが足りないのでしょうか、それとも、ケースのリストを維持してそれらをナビゲートする独自のクラスを作成する必要がありますか?

4

3 に答える 3

12

これはあなたの仕事をするはずです:

public class Main {
    public static void main(String[] args) {
        final LinkedList<String> list = new LinkedList<String> ();

        list.add ("1"); list.add ("2"); list.add ("3"); list.add ("4");

        final MyIterator<String> it = new MyIterator (list.listIterator());

        System.out.println(it.next());
        System.out.println(it.next ());
        System.out.println(it.next ());
        System.out.println(it.previous ());
        System.out.println(it.previous ());
        System.out.println(it.next ());
    }

    public static class MyIterator<T> {

        private final ListIterator<T> listIterator;

        private boolean nextWasCalled = false;
        private boolean previousWasCalled = false;

        public MyIterator(ListIterator<T> listIterator) {
            this.listIterator = listIterator;
        }

        public T next() {
            nextWasCalled = true;
            if (previousWasCalled) {
                previousWasCalled = false;
                listIterator.next ();
            }
            return listIterator.next ();
        }

        public T previous() {
            if (nextWasCalled) {
                listIterator.previous();
                nextWasCalled = false;
            }
            previousWasCalled = true;
            return listIterator.previous();
        }

    }   
}

そしてそれのためのフィドル

于 2012-11-20T22:44:01.133 に答える
2

ListIteratorは、このように動作するように設計されています。理論的根拠については、ShyJの回答の下にある会話を参照してください。

私はこの振る舞いがばかげていることを超えていることに気づき、代わりに非常に単純な代替案を書きました。ArrayListsの拡張関数を使用したKotlinコードは次のとおりです。

class ListIterator<E>(var list: ArrayList<E>) : Iterator<E> {

    private var cursor: Int = 0

    fun replace(newList: ArrayList<E>) {
        list = newList
        cursor = 0
    }

    override fun hasNext(): Boolean {
        return cursor + 1 < list.size
    }

    override fun next(): E {
        cursor++
        return current()
    }

    fun hasPrevious(): Boolean {
        return 0 <= cursor - 1
    }

    fun previous(): E {
        cursor--
        return current()
    }

    fun current(): E {
        return list[cursor]
    }

}

fun <E> ArrayList<E>.listFlippingIterator() = ListIterator(this)

削除機能を含めたい場合は、APIを作成して、イテレータが左または右のどちらを削除するかを明示的に指示することを強くお勧めします。たとえば、これらのメソッドをremoveNext()ととして定義しremovePrevious()ます。

于 2017-12-18T12:52:26.370 に答える
-1

このようなことをしてください(擬似コード)-

class SkipIterator extends ListIterator {

    public E previous(){
        E n = super.previous();
        return super.previous();
    }

    ...

}

それから:

LinkedList<String> navigationCases;
navigationCases.add("page1");
navigationCases.add("page2");
navigationCases.add("page3");
navigationCases.add("page4");

SkipIterator navigationItr = (SkipIterator)navigationCases.listIterator();
navigationItr.next(); // Returns page1
navigationItr.next(); // Returns page2
navigationItr.previous(); // Returns page1

乾杯

于 2012-11-20T22:28:10.730 に答える