2009-05-04 15 views
26

Javaでは、私のメソッドからIteratorを返す必要があります。私のデータは通常、私にイテレータを与えることができるので、私はそれを返すことができる別のオブジェクトから来ますが、場合によっては基底のデータがnullです。一貫性を保つために、その場合は "空の"イテレータを返したいので、呼び出し側がnullをテストする必要はありません。パラメータ化された型の空のコレクションのJavaイテレータ

私のような何か書きたい:

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>)へのキャスティングも機能しません。

答えて

56

は、次の構文を通じてFoo型の空のリストを取得することができます。

return Collections.<Foo>emptyList().iterator(); 
+0

私はちょうど時々迅速になろうとしていることを発見したが、あなたが遅くなります。私は空のイテレーターの実装を書いて、私がバニー・トレイルに乗っていたのを見つけるためにここに戻りました。 +1 –

+2

Java 1.7 Collections APIでは 'Collections.emptyIterator()'が拡張されました。 –

0

申し訳ありませんが、私はそれを考え出しました。コンパイラがパラメータ化された型を理解できるように、代入を使用する必要があります。

public Iterator<Foo> iterator() { 
    if (underlyingData != null) { 
     return underlyingData.iterator(); 
    } else { 
     List<Foo> empty = Collections.emptyList(); // param type inference 
     return empty.iterator(); 
    } 
} 
+0

私の解決策を打ち込む前から、アレックスBは答えました。私はemptyList()によって返されたパラメータ化された型の構文が欠けていました。割り当ては機能しますが、1つのライナーはさらに優れています。 – miner49r

9

私は特別なケースとリターンを扱う、

public Iterator<Foo> iterator() { 
    if (underlyingData == null) 
     return Collections.<Foo> emptyList().iterator(); 
    return underlyingData.iterator(); 
} 

だけのラインに沿ってより多くを行くと思い、その後、通常のケースを扱います。しかし、私の主なポイントは、あなたが

Collections.<Foo> emptyList().iterator(); 
+0

+1特殊ケースのみを処理し、 'else'を取り除く –

+0

IMO、この場合nullとnull以外の値は等しく特別です。それ以外はここではっきりしています。 –

+0

あなたはYOの権利を持っていますが、私にとっては、このクラスが空のリストを含むすべてのリストを処理しているように見えます。空リストであるかのように特別にnullを処理しています。通常はunderlyingDataに委譲し、できない場合は特別なものを製造します。 –

2

で割り当てを避けることができるということです私は、これはJavaの型推論は、すべてのケースでは動作しないことと、三項演算子は常に明らかに、もし他の同等のと等価ではないことを示していると思います構築する。

も避けたいnullです。また、奇妙なステートフルな動作(Iterableを好む)があるので、Iteratorを渡すのは避けてください。あなたがこれを行うための合法的な、非未熟な理由を持っていると仮定しかし、これを書いている私の好ましい方法は、IMO

public Iterator<Foo> iterator() { 
    return getUnderlyingData().iterator(); 
} 
private List<Foo> getUnderlyingData() { 
    if (underlyingData == null) { 
     return Collections.emptyList(); 
    } else { 
     return underlyingData; 
    } 
} 

だろう、それが推測できる場合場合でも、(推察型情報を挿入しない方が良いですコードが長くなります)。

ローカル変数を宣言するだけでなく、getUnderlyingDataメソッドを挿入することはほぼ確実です。

あなたは両方の結果についてiteratorと電話しているので、自分自身を繰り返さないでください。

+0

1つの場所からのみiterator()を呼び出すことで、DRYの勝利を+1します。私は、この種のソリューションがunderlyingDataが変更された場所に移動できるかどうか疑問に思います。これは私が思うすべてのDRYestになります。 – CurtainDog

4

Collections.<Foo>emptyList().iterator()の煩さは、Iterators.emptyIterator()google-collectionsに提供する主な理由です。あなたのような場合は、タイプパラメータは必要ありません。

0
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(){ 
     } 
    } 
} 
+0

同じことをする組み込みイテレータがあります: 'Collections.emptyIterator();'。 – assylias

25

Java 7は現在のところ外出中です。以前のバージョンのJavaのために開発している場合を除き、あなたはこのように、空の反復子を返します:

return Collections.emptyIterator(); 
+1

空のイテレータを 'パラメータ'にすることもできます。 emptyIterator() ' – Thomas

関連する問題