2009-04-20 1 views
7

は、私は配列を受け取り、それを使用して各要素を処理するメソッドを持っていると仮定し、Javaのfor-each loopに建てられ、このような:すべてのfor-eachループで動作するJavaで使用できるパラメータはありますか?

public static void myFun(SomeClass[] arr) { 
    for (SomeClass sc : arr) { 
     // Stuff is processed here 
    } 
} 

これはうまく動作しますが、今私が合格できるようにしたいです代わりにList<SomeClass>と同じ方法。私はCollection.toArray(T [])を使うつもりか、for-each構造で使うことができるタイプを受け入れるmyFun()のためのパラメータがありますか?

明示するには:どのような反復可能オブジェクトを受け入れるメソッドシグネチャが必要です。それはプリミティブ配列またはコレクションです。私は非常に簡単に2つのメソッドを記述することができますが、一方はもう一方のメソッドをラップしますが、もっと良い方法があれば好奇心が強いです。

+0

配列はIterableを実装していないので、残念ながら答えはいいえです。 –

答えて

9

私は、パラメータの型としてIterableCollectionまたはListを使用してお勧めします。

IMOでは、配列を参照するにはコレクションを優先する必要があります。あなたが配列を持っている場合は、Arrays.asList変換をうまく行います。 Arrays.asListは、取得と設定をアレイに戻すことができますが、明らかに配列の長さを変更する「構造的な」変更ではありません。

myFun(Arrays.asList(arr)); 

極端な場合や一般的な場合には、ワイルドカードを使用する必要があります。

public static void myFun(Iterable<? extends SomeClass> somethings) { 
    for (SomeClass something : somethings) { 
     // something is processed here 
    } 
} 

それはそのCollections.toArrayArrays.asList仕事若干異なる注目すべきです。 asListは元の配列をコレクションの元に戻すので、コレクションの変更は配列に反映されます。 Collections.toArrayは、コレクションデータの(浅い)コピーを作成します。配列を返すのであれば、コピーを作成することはしばしば必要になります。非対称的に、引数として渡す場合、一般的にコピーしません(フィールドとして格納しない限り)。

+0

私は同意します。このような場合はIterableを使用します。これは実装者に負担を最小限に抑えるからです。 Object []では直接動作しませんが、これをArrays.asList()で橋渡しするのは簡単です。 – erickson

+0

うん。 OTOHでは、イテレーション前にコレクションのサイズが必要になることが考えられ、ほとんどのコードでもCollectionが使用されます。 –

+0

asList()またはtoArray()を避ける方法がないように思えば、私はこのロジックに最も賛成です。両方からの入力を期待しているのであれば、Object []の代わりにIterableを使うのは意味があります。 –

5

Iterableを使用してください。それがそれのためのものです。

あなたが言ったように、Iterableは配列を処理しません。

お互いをラッピングする複数のメソッドを使用する必要はありません。それはArrays.asListCollection.toArrayを除外します。

あなたの質問に対する答えはいいえ、方法はありません。しかし、の場合はを使用してください。Listsを使用すると、なぜあなたは配列を使用しますか?

ここでもIterableとします。過去に私がIterableを実装したクラスを持っていたが、コレクションではなかったので、私はCollectionよりも好きです。これにより、必要に応じて遅延的に値を取得することが容易になり、foreachループを使用することができました。

+2

Iterableをパラメータとして使用すると、プリミティブ配列を渡すときにコンパイルエラーが発生します。 –

+0

おっと、それは考えていませんでした。私はちょっと考えてみましょう... –

+0

Is Object [] Iterable ?? –

-3
public static void myFun(Collection<MyClass> collection) { 
    for (MyClass mc : collection) { 
     // Stuff is processed here 
    } 
} 
+0

MyCalss。 –

+0

これは配列を渡すと機能しません –

3

あなたがことはできませんが、Java配列を反復処理可能を実装していません:

public static int sum(Iterable<Integer> elements) { 
    int s = 0; 

    for (int i : elements) { 
     s += i; 
    } 

    return s; 
} 

public static void main(String[] args) { 
    L1: System.out.println(sum(1,2,3)); 
    L2: System.out.println(sum(Arrays.asList(1,2,3))); 
    L3: System.out.println(sum(new int[] { 1,2,3 })); 
} 

これは(L1とL3)の2コンパイル時エラーになります。あなたが反復処理可能(コレクション)、および/または配列を受け入れるように 方法を設計する必要があり、少なくとも一つの方法は、(へ/配列から)

回避策いくつかの変換を実行する必要があります。

あなたは試すかもしれ

public class ArrayIterator<T> implements Iterator<T> { 

    private final T[] array; 
    private int i; 

    public ArrayIterator(T[] anArray) { 
     array = anArray; 
     i = 0; 
    } 

    public boolean hasNext() { 
     return i < array.length; 
    } 

    public T next() { 
     return array[i++]; 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
} 

private static int sum(final Integer ... elements) { 
    return sum(new Iterable<Integer>() { 

     public Iterator<Integer> iterator() { 
      return new ArrayIterator<Integer>(elements); 
     } 
    }); 
} 

プリミティブ配列を扱う場合にのみ注意してください。あなただけ 参照オブジェクト(ご使用の場合)ArrayIterator +匿名クラスを使用する場合

はそれが

0

を役に立てば幸いクールなあなたは、メソッド呼び出しで<? extends Subtype>を使用できるJava 1.5以降でJavaのジェネリック医薬品の少し既知の機能がありますし、コンストラクタ。 <? extends Object>を使うことができ、それらを扱うものはObjectのメソッドだけにアクセスできます。あなたは(MyCrustaceansのような)基本クラスを持っている場合は、あなたの場合、あなたは、DoStuff(またはObjectクラスの中にその基底クラスのいずれかの方法を使用することができますので、

List<? extends MyCrustaceans> seaLife = new ArrayList<? extends MyCrustaceans>(); 
MyShrimp s = new MyShrimp("bubba"); 
seaLife.add(s); 
DoStuff(seaLife); 

... 

public static void DoStuff(List<? extends MyCrustaceans> seaLife) 
{ 
    for (MyCrustaceans c : seaLife) { 
     System.out.println(c); 
    } 
} 

:何が本当に欲しいかもしれないことは、よりこのようなものですパラメータは<? extends Object>です)。 <? super MyType>と同様の機能があり、サブタイプではなく、指定されたタイプのスーパータイプであるパラメータを受け入れます。このように「拡張」と「超」を使用することにはいくつかの制限があります。ここにはgood place to find more infoがあります。

1

短い答え:いいえ、型定義可能な単一メソッド署名はありません。これは、Iterableと配列の両方を安全に受け入れます。明らかにあなたはObjectを受け入れることができますが、それはハックでもあります。

ロングっぽい答え:強化for -loopが効果的に(Iterableのための配列や、一度に一度)を2回定義されているので、あなたにも2つのオーバーロードされたメソッドを提供する必要がありますが、

public static void myFun(SomeClass[] array) { 
    for (SomeClass sc : array) { 
     doTheProcessing(sc); 
    } 
} 

public static void myFun(Iterable<? extends SomeClass> iterable) { 
    for (SomeClass sc : iterable) { 
     doTheProcessing(sc); 
    } 
} 

2つのメソッドのソースがまったく同じように見える場合は、2回定義する必要があります(もちろん、@ dfaのように自分で配列を自分のIterableにラップしない限り)。

+0

"明快にするために、反復可能なオブジェクトを受け入れるメソッドシグネチャが必要です。これはプリミティブ配列またはコレクションです。私は非常に簡単に2つのメソッドを記述できます。しかし、より良い方法があれば、私はちょうど興味がある」 –

+0

さて、私は十分に質問を読まなかった。私はこれがより良いことを願っています。 –

+1

ええ、本当に他の答えはありません。すべての "回答"は回避策またはアドバイスに過ぎません。 –

関連する問題