List<String> names = List.of("Tanaka", "Sato", "Suzuki");
List.of()。
変更できないリストを、一行で作る。
なるほど、そういうことか。
ようやく腑に落ちた。
そして今日、また若手のコードを見た。
Set<String> roles = Set.of("ADMIN", "USER", "GUEST");
……また of() だ。
今度は Set か。
Map にもあるんじゃないか、と思って探したら、あった。
Map<String, Integer> scores = Map.of(
"Tanaka", 90,
"Sato", 75,
"Suzuki", 88
);
Map.of() まである。
List、Set、Map。
全部 of() で作れるようになっていた。
■ Java7以前、Setはどう書いていたか
まず、Setを思い出す。Set<String> roles = new HashSet<>();
roles.add("ADMIN");
roles.add("USER");
roles.add("GUEST");
これが普通だった。
あるいは、こう書く人もいた。
Set<String> roles = new HashSet<>(Arrays.asList("ADMIN", "USER", "GUEST"));
1行にはなる。
だが、new HashSet<> に Arrays.asList を渡す。
読めなくはないが、すっきりはしない。
■ Java7以前、Mapはどう書いていたか
Mapはもっと面倒だった。Map<String, Integer> scores = new HashMap<>();
scores.put("Tanaka", 90);
scores.put("Sato", 75);
scores.put("Suzuki", 88);
put、put、put。
エントリの数だけ行が増える。
初期データを定義したいだけなのに、
ずいぶん手間がかかった。
■ Java9ではどう書くか
// Set
Set<String> roles = Set.of("ADMIN", "USER", "GUEST");
// Map
Map<String, Integer> scores = Map.of(
"Tanaka", 90,
"Sato", 75,
"Suzuki", 88
);
短い。
意図が見える。
■ SetやMapそのものは変わっていない
念のため確認した。HashSet も HashMap も、使い方は昔のままだ。
Set や Map というインターフェースの仕様も変わっていない。
変わったのは一点だけ。
インターフェースに 静的ファクトリメソッド が追加された。
of() は、「こういうSetを作れ」という命令ではなく、
「変更不可のSetを手軽に作るための入口」として追加されたメソッドだ。
昔の new HashSet<>() が消えたわけではない。
選択肢が増えた、ということだ。
■ ひとつだけ、引っかかった
Setを触っていて、気づいた。Set<String> ng = Set.of("A", "A"); // 実行時例外
重複した値を渡すと、例外が飛ぶ。
Setは重複を許さない。
それはJava7以前から変わっていない。
new HashSet<>() で add("A") を2回呼んでも、
黙って無視されるだけだった。
だが Set.of() では、例外になる。
厳しくなった。
渡す前に重複がないか、気をつける必要がある。
■ Mapで10個を超えたら
若手のコードにこんなものがあった。Map<String, Integer> scores = Map.ofEntries(
Map.entry("Tanaka", 90),
Map.entry("Sato", 75),
Map.entry("Suzuki", 88),
Map.entry("Yamada", 95),
Map.entry("Ito", 82)
);
Map.ofEntries()?
Map.entry()?
また知らないものが出てきた。
調べると、Map.of() はキーと値のペアが 10個まで という制限がある。
それを超える場合は Map.ofEntries() を使う、ということらしい。
Map.entry() は、キーと値のペアを1つ作るメソッドだ。
なるほど。
知らないと、また止まるところだった。
■ 3つを並べると
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
Map<String, Integer> map = Map.of("A", 1, "B", 2);
List、Set、Map。
全部 of() で作れる。
書き方が統一された。
Java7以前は、それぞれ作り方が違った。
今は、同じ感覚で書ける。
■ 変更できない、という設計
List.of() のときも感じたが、
これらはすべて変更できない。
roles.add("MANAGER"); // 実行時例外
scores.put("Kato", 70); // 実行時例外
追加も削除も、できない。
Java7以前の感覚だと、
「とりあえず new HashMap<>()」だった。
変更するかどうかは、後で考えればいい。
だが若手は最初から変更しない前提で書いている。
設計の向きが、少し違う。