概要
Enum は定義して switch で分岐するだけでなく、EnumSet や EnumMap といった専用コレクション、Stream API との組み合わせで真価を発揮します。たとえば「平日だけの曜日セット」を EnumSet.range で一発で作れますし、「優先度ごとのタスク一覧」を EnumMap で管理すれば定義順のソートが自動で手に入ります。しかし Java 8 の switch 文と Java 14 以降の switch 式では書き方が大きく変わり、Stream の書き方にも差があるため、プロジェクトの Java バージョンに合わせた書き分けが必要です。この記事では、switch 文から switch 式への移行パターン、Stream で Enum をフィルタリング・変換する方法、EnumSet と EnumMap の使いどころを整理します。Java 21 のパターンマッチング switch で when ガードを使った条件分岐も含め、バージョンごとの書き方を対比します。
使いどころ
勤怠システムで EnumSet.range(MONDAY, FRIDAY) を平日セットとして定義し、打刻日が平日かどうかを contains で判定する
タスク管理ツールで EnumMap<Priority, List<Task>> を使い、優先度順に自動ソートされたタスク一覧を構築する
Stream で Enum.values() をフィルタリングし、特定条件に合致する区分値だけを画面のプルダウン選択肢として返す
コード例
import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.stream.Collectors;
public class EnumSwitchStreamExample {
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,
SATURDAY, SUNDAY;
public boolean isWeekend() {
return this == SATURDAY || this == SUNDAY;
}
}
enum Priority {
LOW, MEDIUM, HIGH, CRITICAL;
}
public static void main(String[] args) {
// switch 式で曜日を分類(Java 14+)
var day = Day.WEDNESDAY;
String type = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY -> "平日";
case SATURDAY, SUNDAY -> "休日";
};
System.out.println(day + " は " + type);
// EnumSet: 平日と週末を定義
var weekdays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
var weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
System.out.println("平日: " + weekdays);
System.out.println("週末: " + weekend);
// Stream で週末の曜日をフィルタリング
List<Day> weekendDays = Arrays.stream(Day.values())
.filter(Day::isWeekend)
.collect(Collectors.toList());
weekendDays.forEach(d ->
System.out.println("週末: " + d));
// EnumMap: 優先度ごとのタスク一覧
var taskMap = new EnumMap<Priority, List<String>>(
Priority.class);
taskMap.put(Priority.HIGH,
List.of("サーバー障害対応"));
taskMap.put(Priority.MEDIUM,
List.of("定例ミーティング"));
taskMap.put(Priority.LOW,
List.of("ドキュメント更新"));
// EnumMap は定義順で自動ソートされる
System.out.println("\n=== タスク一覧(優先度順)===");
for (var entry : taskMap.entrySet()) {
entry.getValue().forEach(task ->
System.out.println(
"[" + entry.getKey() + "] " + task));
}
}
}Version Coverage
switch 式(-> 記法)で値を返せる。Stream + filter + collect で宣言的なフィルタリングが可能。var で型推論も利用可。
// Java 17: switch 式 + Stream
var day = Day.WEDNESDAY;
String type = switch (day) {
case MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY -> "平日";
case SATURDAY, SUNDAY -> "休日";
};
// Stream でフィルタリング
List<Day> weekendDays = Arrays.stream(Day.values())
.filter(Day::isWeekend)
.collect(Collectors.toList());Library Comparison
注意点
Java 8 の switch 文では break の書き忘れでフォールスルーが起きる。Java 14 以降の -> 記法なら break 不要でこの問題を回避できる
EnumSet.range は定義順の連続した範囲を取る。途中に要素が挿入されると範囲が変わるため、要素の定義順には注意を払うこと
EnumMap は Enum の定義順でエントリが並ぶ。表示順を定義順と一致させる設計にしておくと、別途ソートが不要になる
Arrays.stream(Enum.values()) は呼び出すたびに配列コピーが発生する。ループ内で繰り返し呼ぶ場合は事前にローカル変数にキャッシュする
Java 21 のパターンマッチング switch で when ガードを使う場合、ガード条件の評価順に注意。具体的なケースを先に書かないと到達不能コードになる
FAQ
Enum をキーにする場合は常に EnumSet を選んでください。内部がビットフラグで実装されており、HashSet より高速かつ省メモリです。
はい。EnumMap は Enum の定義順(ordinal 順)でエントリが並びます。表示順を Enum の定義順と合わせておけば、別途ソートは不要です。
Enum を網羅する switch 式では default を書かないほうが安全です。要素追加時にコンパイルエラーで検出できるため、考慮漏れを防げます。