導入
Javaの正規表現といえば、古くから `Pattern` クラスと `Matcher` クラスを組み合わせて利用するのが一般的でした。しかし、単に「文字列が正規表現に完全に一致するか」を確認したいだけのケースで、毎回 `matcher.matches()` を呼び出すのは、コードの記述量が増えるだけでなく、可読性を損なう要因にもなります。
Java 11で導入された `Pattern.asMatchPredicate()` は、正規表現を `java.util.function.Predicate` 型に変換するメソッドです。これにより、Stream APIとの親和性が劇的に向上し、より簡潔でモダンなJavaプログラミングが可能になります。
基礎知識
`Predicate
一方、`Pattern` クラスは正規表現をコンパイルしたオブジェクトです。通常は `pattern.matcher(input).matches()` とすることで、文字列全体が正規表現にマッチするかを判定します。`asMatchPredicate()` は、内部的にこの「全体一致判定」を行う関数を生成し、`Predicate` として返却する仕組みです。
実装/解決策
`asMatchPredicate()` の最大のメリットは、Stream APIの `filter()` メソッド等に直接渡せる点にあります。従来の匿名クラスやラムダ式で `matcher` を生成していた冗長なコードを排除し、宣言的な記述に置き換えることができます。
サンプルプログラム
以下のコードは、リスト内の文字列から「郵便番号(3桁-4桁)」の形式に合致するものだけを抽出する例です。
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class RegexPredicateSample {
public static void main(String[] args) {
// 郵便番号のパターン(先頭から末尾まで完全に一致する必要がある)
Pattern zipPattern = Pattern.compile(“\\d{3}-\\d{4}”);
List
// asMatchPredicate()を使用してPredicateを生成
List
.filter(zipPattern.asMatchPredicate()) // ここでフィルタリング
.collect(Collectors.toList());
// 結果を出力
System.out.println(“抽出された郵便番号: ” + validZips);
}
}
応用・注意点
1. 完全一致であることに注意
`asMatchPredicate()` は、内部で `Matcher.matches()` を呼び出します。これは「文字列全体」がマッチするかを判定するため、部分一致を期待する場合は注意が必要です。部分一致を行いたい場合は、正規表現の先頭と末尾に `.` を付与するか、別の手法を検討してください。
2. パフォーマンスへの影響
`asMatchPredicate()` は、内部的に `Matcher` インスタンスを生成して利用します。非常に大量のデータを高速に処理する必要がある場合、`Pattern` 自体のコンパイルコスト(`Pattern.compile()`)をループの外側で行うことは必須ですが、`Predicate` 化した後の実行速度は通常の `matches()` と同等です。
3. 名前付きグループとの組み合わせ
正規表現で名前付きグループ(`(?

コメント