改善されたコレクションイテレータ
-
08-07-2019 - |
質問
個人的に、java.util.Iteratorによって提供される機能の範囲はかなり哀れだと感じています。少なくとも、次のようなメソッドが必要です。
- peek()は、反復子を前方に移動せずに次の要素を返します
- previous()は前の要素を返します
first()やlast()など、他にも多くの可能性があります。
そのようなサードパーティのイテレータが存在するかどうかは誰にもわかりませんか?既存のjavaコレクションで動作できるように、おそらくjava.util.Iteratorのデコレーターとして実装する必要があります。理想的には、<!> quot; generics aware <!> quot;である必要があります。
事前に感謝します、 ドン
他のヒント
previous()
を使用するだけでjava.util.ListIterator
を簡単に取得できます。
その時点での覗き見は簡単に実装できます
public <T> T peek(ListIterator<T> iter) throws NoSuchElementException {
T obj = iter.next();
iter.previous();
return obj;
}
残念ながら、各コレクションクラスは独自のイテレータを実装しているため、ユーティリティメソッドとして使用する方が簡単です。ラッパーを実行して、MyListIterator
などのインターフェイスの各コレクションでピークメソッドを取得するのは、非常に多くの作業になります。
これらが実装されていない理由は、一部のコレクションでは重要であり、パフォーマンスに大きな影響があるためだと思います。関心のあるコレクションに対してこの作業を行うのは非常に簡単だと思います。
また、Javaイテレータが移動せずに現在の値を取得する方法がないことも嫌いです(したがって、イテレータを渡すだけで、値に基づいて分岐するコードを簡単に書くことはできません-渡す必要があります現在の値も同様です)。
汎用演算子がこれらの機能を実装しない理由は十分にあります。すべてのコンテナに存在するわけではありません。典型的な例は、ストリームとして見られるファイルのような、外部データ入力を表すコンテナです。値を読み取るたびに、消費し、必要に応じてポインタを前方に移動します。これらの制約を汎用イテレーターに課すと、イテレーターの汎用性が失われます。
提案されているようにprevious
メソッドが必要な場合は、ListIterator<>
を使用します。これは、リストとして動作するコンテナに制限されます。
私が検討することの1つは、clojureでのSeqの実装です
基本クラスの実装はJavaであり、完全なソースが利用可能です。 Seqは、Javaイテレーターのデコレーターです(Javaイテレーターインターフェースを取得および実装します)が、独自のインターフェースを提供します。
ykaganovichが示唆したように、 google-collections をご覧になるとよいでしょう。もの。 ピーク。また、他の一部の人が述べたように、すべてのコレクションにこれらのすべてを実装することは、可能性またはパフォーマンスの観点から危険です。
public class Iterazor<T> {
private Iterator<T> it;
public T top;
public Iterazor(Collection<T> co) {
this.it = co.iterator();
top = it.hasNext()? it.next(): null;
}
public void advance() {
top = it.hasNext()? it.next(): null;
}
}
// usage
for(Iterazor<MyObject> iz = new Iterazor<MyObject>(MyCollection);
iz.top!=null; iz.advance())
iz.top.doStuff();
}
誰かがGoogleコレクションにリンクしているのを見ましたが、探しているメソッドがIterators.peekingIterator()と呼ばれていることを誰も言及していませんでした。
それでも、ListIteratorを使用することができれば最高です。
peek()が必要な問題に遭遇したことはありません。イテレータは私にとってはうまく機能しています。この追加機能が必要だと思うイテレータの使用方法に興味があります。
Stackを使用した方が良いかもしれません。
Javaコレクションは、最小限の便利な機能を提供するために作成されました。これは、Javaを実装するすべての人が 実装するコードにとって非常に優れたアプローチです。 有用かもしれない機能を備えたインターフェースを肥大化させると、コードのボリュームが大幅に増加し、わずかな改善しか認められません。 peek()およびprevious()が標準イテレータの一部であった場合、新しい種類のコレクションを作成するすべての人が、それが賢明であるかどうかにかかわらず、必ず実装する必要があることを意味します。
イテレータは、物理的に 後方に移動できないものでも動作するように設計されているため、peek()とprevious()の両方が不可能になります。