悪あがきプログラマー

悪あがきを続けていきたい技術と書評なブログです。トレタでiOSエンジニアやってます。

list.toArray(new String[list.size()])なの?list.toArray(new String[0)])なの?

list.toArray(new String[list.size()])
って、実はこうやってもかけるんだよね。
list.toArray(new String[0])


だけど、なぜかがわからない。
ちなみに、eclipseをtoarrayで補完すると、(String[]) list.toArray(new String[list.size()])
と、出てくる。

ちょっと調べてみた。
まさに!な記事があった。
@IT:Java TIPS -- 配列とコレクション間の相互変換を行う

  • 引数として与えられた配列に全要素が収まる場合は、引数として与えられた配列に全要素を収め、その配列を戻り値として返す
  • 引数として与えられた配列に全要素が収まらない場合は、引数として与えられた配列と同じ型の配列を新規に生成し、新規に生成された配列に全要素をセットして戻り値として返す
  • コレクションの要素の型が、引数として渡された配列の要素の型に代入できない場合は、例外(java.lang.ArrayStoreException)を発生する
  • toArray(Object[])メソッドの引数に要素が0個の配列をセットすると、引数にセットされた配列と同じ型で、当該Collectionの全要素がセットされた新規配列を返す

じゃぁ、リストのサイズで初期化したときは、全要素が収まるからその引数に渡したオブジェクトが返ってくる訳か。
逆に、サイズを0で指定した場合は、新たに配列を生成したオブジェクトが返ってくると。
てことは、サイズ0指定の方が余分にオブジェクトを生成してしまうのでは?
実験!!

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String[] strs = new String[] { "a", "b", "c", "d", "e" };

		List<String> list = new ArrayList<String>(Arrays.asList(strs)); // 新しいインスタンスを生成

		long sum = 0;
		for (int j = 0; j < 10; j++) {
			long start = System.currentTimeMillis();

			String[] temp = null;
			for (int i = 0; i < 10000000; i++) {
				temp = (String[]) list.toArray(new String[0]);
			}

			long stop = System.currentTimeMillis();
			sum += stop - start;
		}
		System.out.println("toArray(new String[0]) 10000000回の速度*10回の平均速度は " + sum / 10 + " ミリ秒です。");
		
		sum = 0;
		for (int j = 0; j < 10; j++) {
			long start = System.currentTimeMillis();

			String[] temp = null;
			for (int i = 0; i < 10000000; i++) {
				temp = (String[]) list.toArray(new String[list.size()]);
			}

			long stop = System.currentTimeMillis();
			sum += stop - start;
		}
		System.out.println("toArray(new String[list.size()]) 10000000回の速度*10回の平均速度は " + sum / 10 + " ミリ秒です。");
	}
}

さて、気になる実行結果は?

toArray(new String[0]) 10000000回の速度*10回の平均速度は 601 ミリ秒です。
toArray(new String[list.size()]) 10000000回の速度*10回の平均速度は 514 ミリ秒です。

おお、やっぱりtoArray(new String[list.size()])の方が早い!
てことは、基本的にtoArray(new String[list.size()])で書くでいいのかな。

java.util.ArrayListのtoArrayメソッド|ITコンサルタントの読書日記

Date[] resultArray = new Date[arrayList.size()];
arrayList.toArray(resultArray);
return resultArray;

なるほど、こうやって書くとキャストいらないね。


手元にあったフレームワークのソースを見てみたら、
見た感じ全てtoArray(new String[list.size()])だった。
また、中には上で引用した3行で書いてあるのもあった。


とりあえず、結論としては、toArray(new String[0])は遅いからしちゃだめよ、と。
あぁ、スッキリした♪