tl;博士
这里是单线。 (为了好玩,不是我推荐的。)
IntStream
.rangeClosed( 0 , Character.MAX_CODE_POINT )
.filter(
codePoint ->
!
List
.of( Character.CONTROL , Character.FORMAT , Character.SURROGATE , Character.PRIVATE_USE , Character.UNASSIGNED )
.contains( ( byte ) Character.getType( codePoint ) )
)
.forEach(
codePoint -> System.out.println( codePoint + " code point is named: " + Character.getName( codePoint ) + " = " + Character.toString( codePoint ) )
)
;
运行时。
32 code point is named: SPACE =
33 code point is named: EXCLAMATION MARK = !
34 code point is named: QUOTATION MARK = "
…
917997 code point is named: VARIATION SELECTOR-254 = ?
917998 code point is named: VARIATION SELECTOR-255 = ?
917999 code point is named: VARIATION SELECTOR-256 = ?
避免char
Java 中的 char 类型已过时。该数据类型甚至无法表示 Unicode 中定义并受 Java 支持的一半字符。
Java 现在提供对代码点的全面支持。不幸的是,这种支持并不明显,多年后已在 Character、String 和 StringBuilder 类中使用老化的 API。你必须回顾过去涉及char的过时方法。
使用代码点
养成使用 Unicode code point 整数的习惯,不使用任何 char。代码点是分配给 Unicode 定义的 143,859 个字符中的每一个字符的数字。
这些代码点编号的分配范围为 0 到 10FFFF 十六进制,0 到 1,114,111 十进制。显然,这一百万范围内的大部分都是空的,要么当前未分配,要么留作私人使用的储备。
你说:
但是我需要把它升级到 U+231F4。
不,您需要转到 U+10FFFF(十进制 1,114,111)。
顺便说一句,Unicode 一直在增长。因此,不要执着于诸如 143,860 之类的字符数。我们永远不会有太多的表情符号!还有一些严肃的角色还在添加中。
所以你的循环:
for (int i = 0; i < 143_860; i++) { // NO! Wrong limit.
... 需要将其限制从 143_860 更改为 1_114_111 十进制(10FFFF 十六进制)。
for (int i = 0; i < 1_114_111; i++) { // YES! Correct limit.
或者,对于这个限制,使用常量Character.MAX_CODE_POINT。
for (int i = 0; i < Character.MAX_CODE_POINT; i++) { // Use named constant rather than "magic" mystery number.
还有一件事……MAX_CODE_POINT 包含,所以我们应该测试“小于或等于”而不是“小于”。将< 更改为<=。
for (int i = 0; i <= Character.MAX_CODE_POINT; i++) { // Use named constant rather than "magic" mystery number.
Character 类可以告诉我们是否为code point is valid。从 0 到最大 1,114,111 的所有代码点都是有效数字。负数和超过最大值的数字无效。
同一个类可以告诉我们一个代码点代表什么类型的字符。 Unicode 标准定义了 30 种,正式称为“通用类别”。这些类别在Character 类中定义为命名常量,不幸的是与其他不同的常量混合在一起。
我们想跳过其中的某些类别,特别是五个:
Character.CONTROL
Character.FORMAT
Character.SURROGATE
Character.PRIVATE_USE
Character.UNASSIGNED
要确定代码点的类别,请调用Character.getType。不幸的是,该方法仅返回 int 而不是专用的枚举对象。
如上所示,Character 类为通用类别定义了各种byte 常量,但无法将getType 返回的数字轻松转换为类别名称。请参阅相关问题How to get the category name of the character type in Java?。 There is a feature-request 在书上,但尚未实施。所以我们必须自己动手。
这里我们使用一个名为unicodeGeneralCategoryCodesToAvoid 的Byte 对象列表,其中一个元素对应五个感兴趣的常量。
要从代码点 int 数字移动到实际字符,请调用 Character.toString( codePoint ) 以生成包含单个字符的 String。
要获取 Unicode 标准定义的字符的正式名称,请调用 Character.getName( codePoint )。
List < Byte > unicodeGeneralCategoryCodesToAvoid = List.of( Character.CONTROL , Character.FORMAT , Character.SURROGATE , Character.PRIVATE_USE , Character.UNASSIGNED );
for ( int codePoint = 0 ; codePoint <= Character.MAX_CODE_POINT ; codePoint++ ) {
if ( Character.isValidCodePoint( codePoint ) ) // If code point is valid.
{
if ( unicodeGeneralCategoryCodesToAvoid.contains( ( byte ) Character.getType( codePoint ) ) ) // If control character or if unassigned code point, skip it.
{
// No code needed. Skip over this code point as it does not represent a printable character.
} else {
System.out.println( codePoint + " code point is named: " + Character.getName( codePoint ) + " = " + Character.toString( codePoint ) );
}
} else {
System.out.println( "ERROR - Invalid code point number: " + codePoint );
}
}
运行时。
INFO - Demo starting.
32 code point is named: SPACE =
33 code point is named: EXCLAMATION MARK = !
34 code point is named: QUOTATION MARK = "
35 code point is named: NUMBER SIGN = #
36 code point is named: DOLLAR SIGN = $
37 code point is named: PERCENT SIGN = %
…
123 code point is named: LEFT CURLY BRACKET = {
124 code point is named: VERTICAL LINE = |
125 code point is named: RIGHT CURLY BRACKET = }
126 code point is named: TILDE = ~
160 code point is named: NO-BREAK SPACE =
161 code point is named: INVERTED EXCLAMATION MARK = ¡
162 code point is named: CENT SIGN = ¢
…
917997 code point is named: VARIATION SELECTOR-254 = ?
917998 code point is named: VARIATION SELECTOR-255 = ?
917999 code point is named: VARIATION SELECTOR-256 = ?
INFO - Demo ending.
有关我处理 Unicode 通用类别的更多代码,请参阅问题my AnswerHow to get the category name of the character type in Java?。