パラメータ化された型の空のコレクションに対するJavaイテレータ
-
03-07-2019 - |
質問
Javaでは、メソッドからイテレータを返す必要があります。私のデータは別のオブジェクトから取得されるので、通常はイテレーターを提供できるので、それを返すことができますが、状況によっては基礎となるデータがnullになります。一貫性を保つために、<!> quot; empty <!> quot;を返します。その場合、イテレータを使用するため、呼び出し元はnullをテストする必要がありません。
次のようなものを書きたかった:
public Iterator<Foo> iterator() {
if (underlyingData != null) {
return underlyingData.iterator(); // works
} else {
return Collections.emptyList().iterator(); // compiler error
}
}
しかし、Javaコンパイラは、Iterator<Object>
ではなくIterator<Foo>
を返すことについて文句を言います。 (Iterator<Foo>)
へのキャストも機能しません。
解決
次の構文を使用して、Foo型の空のリストを取得できます。
return Collections.<Foo>emptyList().iterator();
他のヒント
Java 7は長い間使用されていません。以前のJavaバージョン用に開発している場合を除き、次のような空のイテレーターを返します。
return Collections.emptyIterator();
次の行に沿ってもっと行きたいです
public Iterator<Foo> iterator() {
if (underlyingData == null)
return Collections.<Foo> emptyList().iterator();
return underlyingData.iterator();
}
特別なケースを処理して戻り、通常のケースを処理します。しかし、私の主なポイントは、割り当てを回避できることです
Collections.<Foo> emptyList().iterator();
Collections.<Foo>emptyList().iterator()
の迷惑が google-collections でIterators.emptyIterator()
を提供する主な理由です。あなたのような場合、型パラメータは必要ありません。
これは、Javaの型推論がすべての場合に機能するわけではなく、三項演算子が明らかに同等のif-else構造と必ずしも同等ではないことを示していると思います。
避けるnull
も述べたい。また、Iterator
を渡すことも避けてください。奇妙なステートフル動作を持っているためです(Iterable
を優先)。ただし、これを行うための正当な、時期尚早な理由があると仮定すると、それを書くための私の好ましい方法は
public Iterator<Foo> iterator() {
return getUnderlyingData().iterator();
}
private List<Foo> getUnderlyingData() {
if (underlyingData == null) {
return Collections.emptyList();
} else {
return underlyingData;
}
}
IMO、推測可能な型情報を推論できる場合は挿入する方が良い(コードが長くなる場合でも)。
ほぼ確実に複数回実行するため、ローカル変数を宣言するだけでなく、getUnderlyingData
メソッドを挿入します。
両方の結果でiterator
を呼び出しているので、繰り返してはいけません。
すみません、わかりました。コンパイラーがパラメーター化された型を判別できるように、割り当てを使用する必要があります。
public Iterator<Foo> iterator() {
if (underlyingData != null) {
return underlyingData.iterator();
} else {
List<Foo> empty = Collections.emptyList(); // param type inference
return empty.iterator();
}
}
public final class EmptyIterator{
public static Iterator iterator(){
return new Empty();
}
private static class Empty implements Iterator {
public boolean hasNext(){
return false;
}
public Object next(){
throw new NoSuchElementException();
}
public void remove(){
}
}
}