List→配列変換は「柔らかい入れ物を“カチッとした形”にする」技
Java では、業務ロジックは List で書きたいけれど、
古いライブラリやフレームワークの引数が「配列(String[] など)」を要求してくる、ということがよくあります。
その橋渡しをするのが「List→配列変換」です。
“柔らかく扱いやすい List” を、“決まった形の配列”に変えて渡すイメージを持ってください。
基本形:toArray(T[]::new) を使った変換
一番素直で、今どきの書き方
List<String> を String[] に変換する、いちばん素直な書き方はこれです。
import java.util.List;
public class ListToArrayBasic {
public static void main(String[] args) {
List<String> names = List.of("山田", "佐藤", "鈴木");
String[] array = names.toArray(String[]::new);
for (String s : array) {
System.out.println(s);
}
// 山田
// 佐藤
// 鈴木
}
}
Javaここでの重要ポイントは二つです。
一つ目は、「toArray(String[]::new) が、“List のサイズにぴったりの String[] を作ってくれる”」ということです。
自分で new String[names.size()] と書かなくても、List がいい感じに配列を用意してくれます。
二つ目は、「戻り値の型がきちんと String[] になる」ことです。Object[] ではなく、ちゃんと具体的な型の配列が欲しいときは、この書き方が基本形になります。
古い書き方:toArray(new String[0]) との違い
どちらも動くが、今は T[]::new を覚えよう
昔からよく見かけるのは、こちらの書き方です。
String[] array = names.toArray(new String[0]);
Javaこれも結果としては同じように String[] が得られます。
toArray(new String[0]) と toArray(String[]::new) の違いは、主に書き味とパフォーマンスの細かい話です。
初心者のうちは、「“具体的な型の配列が欲しいときは toArray(型[]::new)”」と覚えておけば十分です。
ジェネリックなユーティリティにまとめる
「List→配列」を名前付きの関数にしてしまう
毎回 list.toArray(String[]::new) と書くのがうるさく感じてきたら、
ユーティリティメソッドにまとめてしまうのも手です。
import java.util.List;
import java.util.function.IntFunction;
public final class ListArrays {
private ListArrays() {}
public static <T> T[] toArray(
List<T> list,
IntFunction<T[]> generator
) {
if (list == null || list.isEmpty()) {
return generator.apply(0);
}
return list.toArray(generator);
}
}
Java使い方はこうなります。
List<String> names = List.of("山田", "佐藤");
String[] array = ListArrays.toArray(names, String[]::new);
Javaここでの重要ポイントは三つです。
一つ目は、「null や空 List のときに“長さ0の配列”を返す」ことです。
呼び出し側は「とりあえず配列が欲しい」とだけ考えればよく、null チェックを毎回書かなくて済みます。
二つ目は、「IntFunction<T[]> generator に String[]::new のような“配列の作り方”を渡している」ことです。
これにより、どんな型の List にも汎用的に使えるユーティリティになります。
三つ目は、「ListArrays.toArray(list, String[]::new) という名前付きの呼び出しで、“List→配列変換をしている”ことが一目で分かる」ことです。
プリミティブ型の List から配列への変換
List<Integer> → int[] などのパターン
List<Integer> から Integer[] への変換は、先ほどと同じです。
List<Integer> list = List.of(1, 2, 3);
Integer[] boxed = list.toArray(Integer[]::new);
Javaしかし、業務では「int[] が欲しい」こともあります。
その場合は、Stream を使って変換します。
import java.util.List;
List<Integer> list = List.of(1, 2, 3);
int[] primitive =
list.stream()
.mapToInt(Integer::intValue)
.toArray();
Javaここでの重要ポイントは、
「mapToInt で IntStream に変換し、toArray() で int[] を得る」という流れです。
List<Long> → long[] なら mapToLong(Long::longValue)、List<Double> → double[] なら mapToDouble(Double::doubleValue) という形になります。
List→配列変換をどこで使うか
例1:可変長引数メソッドに渡すとき
Java の可変長引数(String... args)は、内部的には配列です。
public void sendMail(String... toAddresses) {
// 実体は String[]
}
JavaList<String> を持っていて、このメソッドに渡したいときは、
List→配列変換が必要になります。
List<String> toList = List.of("a@example.com", "b@example.com");
sendMail(toList.toArray(String[]::new));
Java例2:古いAPIが配列を要求してくるとき
古いライブラリや JDBC の一部 API など、
今でも「String[] を渡してください」というインターフェースは残っています。
そのときに、業務ロジック側は List で持っておき、
「渡す直前だけ配列に変換する」というのが、よくあるパターンです。
まとめ:List→配列ユーティリティで身につけてほしい感覚
List→配列変換は、
単に「メソッドの書き方を覚える」話ではなく、
「List で書かれた世界と、配列を要求する世界の“橋渡し”をどう設計するか」です。
具体的な型の配列が欲しいときは list.toArray(型[]::new) を基本形として覚える。
null や空 List の扱いをユーティリティに閉じ込めて、呼び出し側をシンプルにする。
プリミティブ配列が欲しいときは、mapToInt などのプリミティブ Stream から toArray() する。
「内部では List で扱い、外部APIに渡す直前だけ配列に変換する」という構造を意識する。
あなたのコードのどこかに、
「配列を前提にしたロジックがベタッと書かれている」箇所があれば、
それを一度「内部は List、境界で List→配列変換」に整理できないか眺めてみてください。
その小さな整理が、
「データ構造を“使いやすさ”と“境界の都合”の両方から設計できるエンジニア」への、
確かな一歩になります。
