コレクションを配列に変換する最も簡単な方法は?


125

があると仮定しCollection<Foo>ます。それをに変換するための最良の(現在のコンテキストではLoCで最も短い)方法はFoo[]何ですか?任意のよく知られたライブラリが許可されています。

UPD:;:どのような変換については(このセクションの1以上の場合休暇のコメントをあなたはそれの価値はそれのために別のスレッドを作成すると考えられる場合)Collection<Foo>Bar[]どこBarタイプの1つのパラメータでコンストラクタを持ってFooすなわちpublic Bar(Foo foo){ ... }


JDK-11で導入された代替APIでこの答え出し、同じ操作を同じようなパフォーマンスで実行し、それに沿って説明しました。さらに、構文Stream.toArrayはJDKの既存のAPIと一致します。
ナマン2018

回答:


256

xコレクションはどこにありますか:

Foo[] foos = x.toArray(new Foo[x.size()]);

35
よりシンプル(簡単)ですが、最適ではありません(メモリ):x.toArray(new Foo[0]) --- ドキュメンテーション:読む時間はありません...
user85421

6
@Carlosは実際には、よりも優れたメモリを使用します(new Foo[0])。Collection.toArrayのドキュメントのとおり、 `@param aこのコレクションの要素が格納される配列(十分な大きさの場合)。つまり、新しい配列に直接格納されます。サイズ0の配列を指定すると、新しい配列が作成されます。つまり、不要な場合は、小さな配列と大きな配列が作成されます。
corsiKa 2010

4
@glowcoder-空の配列を静的定数として一度定義すると、これを最小限に抑えることができます。toArray正しい型のターゲット配列を作成するためのヒントにすぎません。そして、この場合、正直に言って、アプリケーションに1つの空の配列が1つ余分にあるかどうかは気にしません。それはノイズレベルをはるかに下回っています。
Andreas Dolk 2010

2
@glowcoder-それがまさに私が(しようとした)を使用した方new Foo[0]がシンプルであるが「最善ではない(メモリ)」と書いた理由です...つまり、私のソリューションは簡単ではあるが最善ではないということです(それが私が使用した理由です:)。
user85421 2010

21
同期されたコレクションを使用している場合でも、このコードはスレッドセーフではないことに注意してください。ほとんどの状況でそれ自体が動作しますが、x.size()とx.toArray()の呼び出しの間にアイテムが削除されると、結果の配列の最後に余分なnull要素が含まれます。new Foo[0]カルロスによって提案されたバリアントは、この問題は生じません。
ジュール、

36

Java 8を使用して更新された質問の代替ソリューション:

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);

35
これはに短縮することができます Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);
lpandzic

構文については、私は受け入れられた答えをはるかに好みます。すべての人がPythonに切り替えられることを願っています。
Eric Chen

@EricChen Pythonへの切り替え-Javaから解釈され動的に型付けされた言語-コーディング構文と番号行が異なるために「コンパイルされた型と静的に型付けされた言語」?良い考えではありません。
RafiAlhamd

10

複数回またはループで使用する場合は、定数を定義できます

public static final Foo[] FOO = new Foo[]{};

そしてそれを好きなように変換します

Foo[] foos = fooCollection.toArray(FOO);

このtoArrayメソッドは空の配列を取得して、ターゲット配列の正しいタイプを判別し、新しい配列を作成します。


これが私のアップデートの提案です:

Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos) 
    temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});

1
ups、constJava ではありません!public static final Foo[] FOO = {}
user85421 2010

1
なぜそれが公開されるのですか?
ゾルタン2013

@ゾルタン-なんで?不変なので、安全性の問題はありません。少し乱雑ですが、他のコードで役立つ可能性があるため、通常は無害です。たぶん、これらすべての定数を使って中央クラスを作成し、それを使っimport staticてそれらを取得することもできます。
ジュール

@Jules配列への参照は不変ですが、その内容は不変です。クラス外の誰もが配列の要素を自由に置き換えることができます。一方、経験則として、クラスの外で必要になるまで、すべてのフィールドを非公開にする必要があると思います。
ゾルタン2013年

2
長さがゼロであるため、変更できるコンテンツはありません
Jules

5

JDK / 11では、a Collection<Foo>をan に変換する別の方法として、次のFoo[]ものを利用できますCollection.toArray(IntFunction<T[]> generator)

Foo[] foos = fooCollection.toArray(new Foo[0]); // before JDK 11
Foo[] updatedFoos = fooCollection.toArray(Foo[]::new); // after JDK 11

@Stuartがメーリングリストで説明しているように(私の強調)、これのパフォーマンスは基本的に既存のものと同じであるはずですCollection.toArray(new T[0])-

結論としては、Arrays.copyOf()を使用する実装が最も速いということです。おそらくそれが組み込みであるためです。

配列全体が上書きされることがわかっているため、新しく割り当てられた配列がゼロで埋められるのを回避できます。これは、パブリックAPIの外観に関係なく当てはまります。

JDK内のAPIの実装は次のとおりです。

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

デフォルトの実装ではgenerator.apply(0)、長さ0の配列を取得するために呼び出し、次に単にを呼び出しますtoArray(T[])。これはArrays.copyOf() 高速パスを経由するため、本質的にと同じ速度toArray(new T[0])です。


:-値のあるコードに使用する場合、APIの使用は後方非互換性に沿って誘導されるだけnullです。たとえばtoArray(null)、これらの呼び出しは既存のためにあいまいになりtoArray(T[] a)、コンパイルに失敗するためです。



3

オリジナルについてはdoublepの回答を参照してください。

Foo[] a = x.toArray(new Foo[x.size()]);

アップデートについて:

int i = 0;
Bar[] bars = new Bar[fooCollection.size()];
for( Foo foo : fooCollection ) { // where fooCollection is Collection<Foo>
    bars[i++] = new Bar(foo);
}    

3

更新セクションのケースの最終的な解決策は次のとおりです(Googleコレクションの助けを借りています):

Collections2.transform (fooCollection, new Function<Foo, Bar>() {
    public Bar apply (Foo foo) {
        return new Bar (foo);
    }
}).toArray (new Bar[fooCollection.size()]);

しかし、ここでの重要なアプローチは、doublepの回答で言及されいました(toArrayメソッドを忘れていました)。


1
スレッドセーフティに関するdoublepの回答に関する私のコメントを参照してください。これは、このソリューションにも適用されます。 new Bar[0]問題を回避します。
ジュール

-1

たとえば、Studentクラスの要素を持つコレクションArrayListがあるとします。

List stuList = new ArrayList();
Student s1 = new Student("Raju");
Student s2 = new Student("Harish");
stuList.add(s1);
stuList.add(s2);
//now you can convert this collection stuList to Array like this
Object[] stuArr = stuList.toArray();           // <----- toArray() function will convert collection to array
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.