JDK7/8 新機能総覧:日時 API から Stream API まで実践ガイド

日時 API の刷新

JDK 8 では java.time パッケージが新設され、従来の DateCalendar を置き換える高機能な日時クラス群が提供されています。

  • 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());

タグ: Java8 lambda stream-api Optional localdatetime

6月5日 19:31 投稿