【Java学習|実務向け】Java 9以降のMatcher.replaceAll(Function)で実現する、柔軟かつ安全な動的文字列置換

導入

従来のJavaにおける正規表現置換(replaceAll)は、置換後の文字列を静的に指定するか、または複雑なバックリファレンス($1, $2など)を使う必要がありました。しかし、置換内容をロジックで制御したい場合、これらの手法では限界があります。Java 9で導入されたMatcher.replaceAll(Function)を使用することで、マッチした個別の結果をラムダ式で動的に加工できるようになりました。これにより、コードの可読性が飛躍的に向上し、複雑な文字列変換処理を簡潔に記述できるようになります。

基礎知識

正規表現を用いる際、java.util.regex.Patternクラスでパターンをコンパイルし、Matcherクラスでマッチングを行います。従来、置換にはreplaceAll(String replacement)を使用してきましたが、これは置換後の文字列が固定、あるいは単純なグループ参照に限定されていました。

Java 9から追加されたreplaceAll(Function replacer)は、MatchResult(マッチした情報のインターフェース)を引数に受け取り、Stringを返す関数型インターフェースを渡すことができます。これにより、マッチした部分のキャプチャグループを取得し、その場で計算・変換して置換結果を生成することが可能になりました。

実装/解決策

手順は非常にシンプルです。
1. Pattern.compileで正規表現を定義します。
2. matcher()メソッドでMatcherオブジェクトを作成します。
3. replaceAll()メソッドに、MatchResultを引数に取るラムダ式を渡します。
4. ラムダ式の中でgroup()メソッドを使い、必要に応じて計算処理を行います。

サンプルプログラム

以下のコードは、文字列内の数値を見つけ、それを「数値の二乗」に置換する例です。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexExample {
public static void main(String[] args) {
String input = “ID:10, ID:20, ID:30”;

// 名前付きキャプチャグループを使って数値部分を特定する
Pattern pattern = Pattern.compile(“ID:(?\\d+)”);
Matcher matcher = pattern.matcher(input);

// replaceAllにラムダ式を渡し、マッチした数値を二乗する処理
String result = matcher.replaceAll(mr -> {
// グループ名「number」で取得した値を数値に変換
int value = Integer.parseInt(mr.group(“number”));
// 計算結果を文字列として返す(これが置換後の値になる)
return “ID:” + (value value);
});

// 結果: ID:100, ID:400, ID:900
System.out.println(“置換後の文字列: ” + result);
}
}

応用・注意点

現場での活用において、以下の点に注意してください。

1. パフォーマンスの考慮
非常に長い文字列や、大量の置換が発生するループ内での正規表現利用は、オーバーヘッドが大きくなる可能性があります。頻繁に呼び出される場合は、Patternオブジェクトをstatic finalフィールドとして保持し、再利用することを徹底してください。

2. 例外処理
ラムダ式内でInteger.parseIntなどの変換を行う際、正規表現で漏れた文字が混入すると例外が発生します。正規表現の精度を上げることと、ラムダ式内での安全なパース(またはtry-catch)を意識してください。

3. 名前付きグループの活用
今回の例のように名前付きキャプチャグループ((?…))を組み合わせると、インデックス($1など)に依存しない保守性の高いコードが書けます。これはチーム開発においてバグを減らすための重要なプラクティスです。

コメント

タイトルとURLをコピーしました