-4

私のフレームワークは次のようなイテレータでいっぱいです

int n = col.getSize();
for (int i = 0 ; i != n; i++) {
  Type obj = col.get(i);

そして、インデックス上でアイテムを反復処理するすべてのプログラムには、このようなコードが含まれていると思います。きちんとしたforeachに比べて醜い感じです

for (Type obj : col) {

foreachに移行するには、すべてのコレクションをIterableにする必要があります。つまり、すべてのiterator()メソッドで新しいIteratorを作成する必要があります。今、私はその使用場所ではなく、すべてのコレクション宣言に醜いコードを持っていました。それで、私は良い仕事をしました、私は醜いコードをcommon.utilsに移しました。

public abstract class ImmutableIterator<T> implements Iterator<T> {
    private int i = 0; 
    private final int size = getSize();

    public abstract int getSize();  // to be implemented by user
    public abstract T getValue(int i); // to be implemented by user

    public T next() { 
        if (!hasNext()) throw new NoSuchElementException(); 
        return getValue(i++);
    }

    public boolean hasNext() { return i != size;}

    public void remove() {
        throw new UnsupportedOperationException("Remove is not implemented");
    }
}

今、私はこの醜いパターンを唯一の場所で分離しました。これが私にできる最善のことです。コレクションはサイズと値(i)を提供します。唯一の問題はパフォーマンスの低下です。最初はhasNextで、もう1つはnext()で、ループ内でサイズチェックを2回実行する必要があります。なぜSunはそのようなクラスを提供しないのだろうか?みんなに必要です。見落としただけですか?

4

2 に答える 2

1

ここで抽象クラスで共有するコードは非常に少ないため、抽象化によるメリットはほとんどありません。このようなイテレータをすべてのコレクションに最初から実装するのも同じくらい簡単だと思います。多くの場合、hasNextたとえば、より直接的に実装できます。

ほら、あなたの抽象クラスには、非抽象コード行と同じくらい多くの抽象行があります。現在、多くのクラスが可変イテレータを実装したいと思うかもしれませんが、抽象クラスには事実上何も残っていません。

さらに、変更する必要はありません。抽象クラスは、バグ修正などの変更を1回行い、同時に複数のクラスを修正できる場合に特に優れています。ただし、このコードは非常に単純なので、このバグはどうなるのでしょうか。たとえば、「削除」の「スロー」にはバグがほとんどない可能性があります。実行しないでください。これを複数のイテレータ間で共有しても、まったくメリットはありません。

于 2012-11-23T19:57:33.683 に答える
0

Tomasz Nurkiewiczは、私たちをグアバに案内しましたUnmodifiableIterator。ただし、ここではremoveメソッドのみが定義されていますが、インデックスの反復も必要です。このヒントにより、LouisWassermanはより良い解決策を見つけることができましたAbstractIndexedListIterator。唯一の欠点は、このクラスがremoveメソッドを実装せず、Guavaパッケージで閉じられることです。これはすべて、そのようなクラスは本当に便利ですが、ユーザーがフレームワークに実装する必要があることを示しています。

JBNizetは別の解決策を提案しました。getSize / GetItem(idx)メソッドの上にイテレーターインターフェイスを実装する代わりに、基になるコレクションから取得したイテレーターインターフェイスを返すことができます。

于 2012-11-24T12:30:52.967 に答える