2009-04-07 2 views
6

は、言う何かのように:その後、「最善」の方法があれば、を使用するために、ある値の束、移入されるようにしたArraysインスタンスメソッドtoArray(T [] a)メソッドに渡すものは?あなたがコレクションのインスタンスを持っている場合

Collection<String> addresses = new ArrayList<String>(); 

型キャストを必要とせずにtoArray()メソッドを使用できますか?

String[] addressesArray = addresses.toArray(new String[] {}); 
String[] addressesArray = addresses.toArray(new String[0]); 
String[] addressesArray = addresses.toArray(new String[addresses.size()]); 
String[] addressesArray = addresses.toArray(new String[addresses.size() + 5]); 

最初の2つの意味に違いはありますか? 3番目に効率的ですか? 4番目は3番目より効率が悪いですか?

答えて

7

a findbugs reportによると、これが最も効率的である:

String[] addressesArray = addresses.toArray(new String[addresses.size()]); 

私はそれらを信じています;)

+2

@AlekseyShipilev http://shipilev.net/blog/2016/arrays-wisdom-ancients/ –

0

これはListインタフェースのjavadocの文書化されています

リストは余裕を持つ指定された配列に収まる場合(つまり、配列がリストより多くの要素を持っている)、配列の要素リストの最後の直後にnullが設定されます。 (これは、呼び出し側がリストにnull要素が含まれていないことを知っている場合にのみ、リストの長さを決定するのに有用である。)

+0

ArrayListのサイズが5で、サイズが10の新しいString配列をtoArray()に渡すとサイズが変更されますが、どちらが多かれ少なかれ適切/効率的かはわかりません。 –

+0

配列のサイズは変更されません。単純にリストの末尾の要素をnullに設定します。 –

0

最初の2つのステートメントで効果的に同じことをしています。

要素が配列に収まらない場合、新しい配列が作成されるため、3番目の方法が最も効率的です。

3

あなたが他人を信用しないことを選択した場合、またはあなた自身をチェックしたい場合は、source for java.util.ArrayListを確認してください(ソースが一部のライセンスに違反している可能性があります。 Sun's JDKをダウンロードすると、すべてのソースコードのコピーも手に入ります)。

<T> T[] toArray(T[] a);のソースコードを確認した後のことが明らかである:

String[] addressesArray = addresses.toArray(new String[addresses.size()]); 

はそれを行うための最速の方法です。

明らかに、ソースコードを読んで理解するのに時間がかかるとは限りません。また、最も効果的なオプションが必ずしも明らかではない場合もありますが、単純な方法ではソースを読むのが非常に参考になります。

5
私のお金のために

String[] addressesArray = addresses.toArray(new String[0]); 

最も簡単な、少なくともエラーが発生しやすいため、 "最高" です。同時コード/同期コレクションで同じコードが機能するという利点もあります。何か違いを生むためには、パフォーマンスの差がごくわずかであるために、実際には低レベルのコードを使用する必要があります。

多くの場合、すべての実行時の割り当てを避けるために、static finalに割り当てられた空の配列が表示されます。明らかに、「最適化」(割り当ては本当に非常に高速です)のためにパフォーマンスが低下する可能性があります。

更新:これは、サイズの大きいアレイを使用するよりも高速です。http://shipilev.net/blog/2016/arrays-wisdom-ancients/tl; dr:リフレクションは、メソッドのルックアップが遅くて簡単なものではなく、すべての要素が書き込まれる(または配列が到達不能になる)と判断できる場合、配列のゼロを削除できます。

+2

+1の記事によると、並行性の問題に気付くと、間違っています。私は一度そのコードでその問題に直面しました:http://github.com/orfjackal/dimdwarf/blob/0d1a0897821a4e0e557a1390a7252a8580d2ec95/dimdwarf-core/src/main/java/net/orfjackal/dimdwarf/scheduler/TaskThreadPool.java#L111 -116 –

+0

通常、私は "addresses.toArray(new String [addresses.size()])"アプローチを使用します。 –

+1

これは簡単で高速です! http://shipilev.net/blog/2016/arrays-wisdom-ancients/ –

1

これは主に理論的な関心のですが、リストは、多くの場合、空である場合は、長さゼロの配列を再利用することができます

private static final String[] EMPTY_STRING_ARRAY = {}; 
... 
String[] addressesArray = addresses.toArray(EMPTY_STRING_ARRAY); 

長さゼロの配列は非ゼロ長の配列とは異なり、(不変であるので、 )、彼らは離れて保存して再利用することができます。

+0

Tom Hawtinの答えを参照してください。 –

関連する問題