日時 API の刷新
JDK 8 では java.time パッケージが新設され、従来の Date/Calendar を置き換える高機能な日時クラス群が提供されています。
- LocalDate:年月日のみを保持(例:2024-05-31)
- LocalTime:時分秒ナノ秒を保持(例:18:07:12.123456789)
- LocalDateTime:上記 2 つの合成(例:2024-05-31T18:07:12.123)
- ZonedDateTime:タイムゾーン付き日時
- Instant:Unix エポックからのナノ秒精度の瞬間
- Duration:時間間隔(LocalTime 差分)
- Period:日付間隔(LocalDate 差分)
- DateTimeFormatter:スレッドセーフなフォーマッタ
ラムダ式 & メソッド参照
関数型インタフェースを実装する際の冗長な匿名クラスを、簡潔な式で記述できるようになりました。
// 従来
Collections.sort(names, new Comparator<String>() {
public int compare(String a, String b) {
return a.compareToIgnoreCase(b);
}
});
// ラムダ式
names.sort((a, b) -> a.compareToIgnoreCase(b));
// メソッド参照
names.sort(String::compareToIgnoreCase);
使用例
// Runnable の簡潔な起動
new Thread(() -> System.out.println("Hello Lambda")).start();
// リストの繰り返し処理
users.forEach(System.out::println);
Stream API による宣言的データ処理
内部イテレータを利用し、フィルタ・マップ・リデュースなどを宣言的に記述できます。並列実行も parallelStream() 一つで切り替え可能です。
中間操作
// 5 文字未満の文字列を大文字に変換
List<String> shortUpper =
words.stream()
.filter(w -> w.length() < 5)
.map(String::toUpperCase)
.collect(Collectors.toList());
終端操作
// 最も若い社員
Employee youngest = roster.stream()
.min(Comparator.comparing(Employee::getAge))
.orElseThrow();
// 統計情報
IntSummaryStatistics stats =
scores.parallelStream()
.mapToInt(Integer::intValue)
.summaryStatistics();
System.out.println("最大値: " + stats.getMax());
System.out.println("平均値: " + stats.getAverage());
その他の便利メソッド
distinct():重複除去skip(n):先頭 n 要素スキップlimit(n):最大 n 要素取得flatMap():ネストしたコレクションをフラット化findFirst():条件に合致する最初の要素を取得
Optional で null を安全に扱う
値の存在/不在を明示し、NullPointerException を回避します。
Optional<User> maybe = Optional.ofNullable(getUser(id));
User user = maybe.orElseThrow(() -> new UserNotFoundException(id));
// 値が存在すれば処理
maybe.ifPresent(u -> log.info("found: {}", u.getName()));
// デフォルト値を遅延生成
String name = maybe.map(User::getName).orElseGet(() -> "Guest");
関数型インタフェース 4 種
| インタフェース | 抽象メソッド | 用途例 |
|---|---|---|
Consumer<T> | void accept(T t) | forEach |
Supplier<T> | T get() | 遅延生成/ファクトリ |
Predicate<T> | boolean test(T t) | filter |
Function<T,R> | R apply(T t) | map |
// 使用例
Predicate<Integer> isEven = n -> n % 2 == 0;
Function<String, Integer> length = String::length;
Supplier<Double> random = Math::random;
Consumer<String> printer = System.out::println;
List<Integer> evens = numbers.stream()
.filter(isEven)
.collect(Collectors.toList());