java.text.BreakIteratorがUnicode拡張書記素クラスタに対応した

製品開発担当の大です。こんにちは。

Java21のリリースが近づいてきましたね!Java17以来2年ぶりのLTSということで、HOSでも検証作業をすすめています。正式なサポートについては今しばらくお待ち下さい。

さて、既存のユニットテストをJava21で動かしていると通らない箇所があったので調査したところ、java.text.BreakIteratorの挙動が変わっていました。BreakIteratorといえば以前「Java17でUnicode拡張書記素クラスタを扱うなら正規表現を使うのが手軽で良さそうです」という記事でもとりあげました。これまで書記素クラスタの分割にはほとんど使えないものだったのですが、いつの間にかちゃんと動くようになっていたのです!

今年3月リリースのJava20で実装されていたようです。ありがたいですね。

https://www.oracle.com/java/technologies/javase/20-relnote-issues.html

core-libs/java.text
➜ Grapheme Support in BreakIterator (JDK-8291660)

Character boundary analysis in java.text.BreakIterator now conforms to Extended Grapheme Clusters breaks defined in Unicode Consortium's Standard Annex #29. This change will introduce intentional behavioral changes because the old implementation simply breaks at the code point boundaries for the vast majority of characters. For example, this is a String that contains the US flag and a grapheme for a 4-member-family.

"🇺🇸👨‍👩‍👧‍👦"

This String will be broken into two graphemes with the new implementation:

"🇺🇸", "👨‍👩‍👧‍👦"

whereas the old implementation simply breaks at the code point boundaries:

"🇺", "🇸", "👨", "(zwj)", "👩", "(zwj)", "👧", "(zwj)"‍, "👦"

where (zwj) denotes ZERO WIDTH JOINER (U 200D).

まとめると以下のようになります。

ICU4J 正規表現 java.text.BreakIterator
Java11以前 ❌(使えない) 🔺(使えるけど不十分)
Java17 🔺(使えるけど不十分)
Java21