はじめに
そもそもJavaでInteger
の配列を扱うことは少ないと思います。
java.util.List
を使うほうが一般的です。これはInteger
の配列をどうしても生成したかったため、筆者が試した記録です。
基本的な定義方法
要素数3のInteger
配列の定義は以下のようになります。
Integer[] numbers = new Integer[3];
このときの配列の中身はnull
が並びます。
Integer[] numbers = new Integer[3];
Arrays.stream(numbers).forEach(System.out::println);
null
null
null
1~NまでのInteger配列を作る
単純にやるのであれば以下の方法でいけます。
private Integer[] createNumbers(int n){
Integer[] numbers = new Integer[n];
for (int i = 0; i < n; i++) {
numbers[i] = Integer.valueOf(i + 1);
}
return numbers;
}
オートボクシングが働くのでInteger#valueOf
はなくても動きます。
private Integer[] createNumbers(int n){
Integer[] numbers = new Integer[n];
for (int i = 0; i < n; i++) {
numbers[i] = i + 1;
}
return numbers;
}
Stream APIを使ってなんとかしたい!
さてintの配列であればStreamを使って作ることができます。
private static int[] createNumbers(int n) {
return IntStream.rangeClosed(1, n).toArray();
}
すっきりしたコードでかけますね。
Integerだとそもそも1~NまでのStreamを作ることが少しめんどくさいです。
private Integer[] createNumbers(int n){
return IntStream.rangeClosed(1, n).mapToObj(Integer::valueOf).toArray(Integer[]::new);
}
以下の手順でIntegerの配列を作ることができます。
-
IntStream
で1~NまでのStreamを作り、 -
mapToObj
でIntegerのStreamに変換し、 -
toArray
で配列に変換
なお、toArray
を引数なしで呼び出すとObject[]
が戻り値になってしまいます。
Stream#toArrayの引数
さてIntStream#toArray
の引数は配列の生成関数(IntFunction<A[]>
)となっています。
これは以下のようなシグネイチャを指します。
A[] function(int i){
return hoge; // A[]型
}
なおJavaDocを見ると、「要求された配列のサイズを表す整数を受け取り」とあります。
軽く検証するために以下のようなコードを実行してみました。
IntStream.rangeClosed(1, n).mapToObj(Integer::valueOf).toArray(i -> {System.out.println(i);return new Integer[i];});
結果は当然nの値が表示されます。たとえばn=3
であれば3
です。
しかし10だけ余裕を持った配列を生成したい場合、以下のように処理を書けば良さそうですがそうはいきません。
private Integer[] createNumbers(int n){
return IntStream.rangeClosed(1, n).mapToObj(Integer::valueOf).toArray(i -> new Integer[i + 10]);
}
実行時エラーとなり、n=3
のときは以下のようなメッセージが出力されます。
java.lang.IllegalStateException: Begin size 3 is not equal to fixed size 13
要素に余裕がほしい場合、(Integerに限らず)Streamは使わないほうが賢明でしょう。
まとめ
普通にforを回す or IntStream.rangeClosed(1, n).mapToObj(Integer::valueOf).toArray(Integer[]::new)
で生成できます。
Stream#toArrayは微妙に使いにくいという印象を受けました。
引数なしでStream<T>.toArray()
の結果はT[]のほうがみんな幸せな気がしますがどういう経緯なんですかね?
初期化用の関数渡せるわりに要素数を指定できないのでT[]::new
以外で使い道がほぼないのに・・・。