如何利用String.codePoints()方法准确获取并处理包含复杂Unicode字符的字符串码点流?
- 内容介绍
- 相关推荐
本文共计933个文字,预计阅读时间需要4分钟。
`String.codePoints()` 是 Java 8 引入的一个用于正确处理 Unicode 字符(尤其是补充字符,即码点大于 `0xFFFF` 的字符)的关键方法。它返回一个 `IntStream`,其中每个元素是一个完整的 Unicode 码点(`int` 类型),而不是 `char` 类型(仅能表示 BMP 中的字符)。这样可以避免将代理对(surrogate pair)错误地成两个无效的 `char` 值。
为什么不能只用 charAt() 或 toCharArray()?
Java 的 char 是 16 位无符号整数,只能表示基本多文种平面(BMP,U+0000–U+FFFF)中的字符。超出该范围的字符(如大多数 emoji、古文字、部分数学符号)在 UTF-16 中以**代理对**(两个连续的 char:高代理 + 低代理)形式存储。例如:
-
"??"(程序员 emoji)实际由 4 个char组成:0xD83D 0xDC68 0x200D 0xD83D 0xDCBB(注意:中间有 ZWJ 连接符,共 5 个码点,但底层是多个代理对) -
"?"(U+20BB7,一个汉字)在字符串中占两个char:0xD842 0xDFB7
若用 charAt(i) 遍历,会把代理对拆开,得到无意义的高位或低位代理值,导致乱码或 Character.isSurrogate() 判定异常。
本文共计933个文字,预计阅读时间需要4分钟。
`String.codePoints()` 是 Java 8 引入的一个用于正确处理 Unicode 字符(尤其是补充字符,即码点大于 `0xFFFF` 的字符)的关键方法。它返回一个 `IntStream`,其中每个元素是一个完整的 Unicode 码点(`int` 类型),而不是 `char` 类型(仅能表示 BMP 中的字符)。这样可以避免将代理对(surrogate pair)错误地成两个无效的 `char` 值。
为什么不能只用 charAt() 或 toCharArray()?
Java 的 char 是 16 位无符号整数,只能表示基本多文种平面(BMP,U+0000–U+FFFF)中的字符。超出该范围的字符(如大多数 emoji、古文字、部分数学符号)在 UTF-16 中以**代理对**(两个连续的 char:高代理 + 低代理)形式存储。例如:
-
"??"(程序员 emoji)实际由 4 个char组成:0xD83D 0xDC68 0x200D 0xD83D 0xDCBB(注意:中间有 ZWJ 连接符,共 5 个码点,但底层是多个代理对) -
"?"(U+20BB7,一个汉字)在字符串中占两个char:0xD842 0xDFB7
若用 charAt(i) 遍历,会把代理对拆开,得到无意义的高位或低位代理值,导致乱码或 Character.isSurrogate() 判定异常。

