Java 中的 white space 包括哪些字符?
要点
结合 www.compart.com/en/unicode/ 提供的 Unicode 字符分类以及 Character.java 中的相关描述,我们可以推知,在 Java 中,有 个字符被视为 white space,下方列举了这 个字符。
- U+0009 (即,
'\t') - U+000A (即,
'\n') - U+000B
- U+000C (即,
'\f') - U+000D (即,
'\r') - U+001C
- U+001D
- U+001E
- U+001F
- U+0020 (即,
' ') - U+1680
- U+2000
- U+2001
- U+2002
- U+2003
- U+2004
- U+2005
- U+2006
- U+2008
- U+2009
- U+200A
- U+2028
- U+2029
- U+205F
- U+3000
其中只有前 个字符是 ASCII 字符。
正文
在 OpenJDK 中的 Character.java 里有 isWhitespace(int) 方法,那么在 java 中,具体有哪些字符是 white space 呢?
isWhitespace(int) 方法的 javadoc 如下 ⬇️
从它的 javadoc 中可以看出,如果一个字符满足下列任何一个条件,则认为它是(java 中的) white space (第一个条件下文会有更多解释)
- 它是
Unicode space character,(即,它属于 Space Separator 或 Line Separator 或 Paragraph Separator,但不是 U+00A0/U+2007/U+202F) - 它是
'\t',即 U+0009,HORIZONTAL TABULATION - 它是
'\n',即 U+000A,LINE FEED - 它是 U+000B,
VERTICAL TABULATION - 它是
'\f',即 U+000C,FORM FEED - 它是
'\r',即 U+000D,CARRIAGE RETURN - 它是 U+001C,
FILE SEPARATOR - 它是 U+001D,
GROUP SEPARATOR - 它是 U+001E,
RECORD SEPARATOR - 它是 U+001F,
UNIT SEPARATOR
关于 SPACE_SEPARATOR/LINE_SEPARATOR/PARAGRAPH_SEPARATOR,我解释一下。
Character.java 中有如下 个字段
根据这 个字段的注释中的描述,我们可以找到它们对应的
Unicode 类别如下 ⬇️
SPACE_SEPARATOR: 和Unicode的 Zs 类别对应LINE_SEPARATOR: 和Unicode的 Zl 类别对应PARAGRAPH_SEPARATOR:Unicode的 Zp 分类对应
Space Separator 类别
Space Separator 类别里共有 个字符
排除掉 U+00A0/U+2007/U+202F 这 个字符后,还剩 个字符 ⬇️
可以列举如下
- U+0020
U+00A0 (要排除掉)- U+1680
- U+2000
- U+2001
- U+2002
- U+2003
- U+2004
- U+2005
- U+2006
U+2007 (要排除掉)- U+2008
- U+2009
- U+200A
U+202F (要排除掉)- U+205F
- U+3000
Line Separator 类别
Line Separator 类别里只有 U+2028 这 个字符 ⬇️
Paragraph Separator 类别
Paragraph Separator 类别里只有 U+2029 这 个字符 ⬇️
小结
综上,一共有 个字符在 java 中被认为是 white space。具体如下 ⬇️
| 分类 | 具体是哪些/哪个字符? | 数量 |
|---|---|---|
| Space Separator 但要排除以下 个字符 U+00A0 U+2007 U+202F | U+0020 U+1680 U+2000 U+2001 U+2002 U+2003 U+2004 U+2005 U+2006 U+2008 U+2009 U+200A U+205F U+3000 | |
| Line Separator | U+2028 | |
| Paragraph Separator | U+2029 | |
'\t' | U+0009 | |
'\n' | U+000A | |
| U+000B | ||
'\f' | U+000C | |
'\r' | U+000D | |
| U+001C | ||
| U+001D | ||
| U+001E | ||
| U+001F |
用代码验证
老规矩,我们还是写点代码来验证一下。请将如下代码保存为 Verify.java。
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Verify {
public static void main(String[] args) {
Set<Integer> realResult = IntStream.rangeClosed(Character.MIN_CODE_POINT, Character.MAX_CODE_POINT).
filter(Character::isWhitespace).
boxed().
collect(Collectors.toCollection(LinkedHashSet::new));
Set<Integer> expectedResult = IntStream.of(
' ', // U+0020
'\u1680',
'\u2000',
'\u2001',
'\u2002',
'\u2003',
'\u2004',
'\u2005',
'\u2006',
'\u2008',
'\u2009',
'\u200A',
'\u205F',
'\u3000',
'\u2028',
'\u2029',
'\t', // U+0009
'\n', // U+000A
'\u000B',
'\f', // U+000C
'\r', // U+000D
'\u001C',
'\u001D',
'\u001E',
'\u001F'
).boxed().collect(Collectors.toSet());
if (realResult.equals(expectedResult)) {
System.out.printf("Java 中一共有 %d 个 white space character%n", expectedResult.size());
System.out.println("这些 character 分别是 ⬇️");
realResult.stream().map(Integer::toHexString). // e.g. '\n' -> "a"
map(String::toUpperCase). // e.g. "a" -> "A"
map(raw -> "U+" + "0".repeat(4 - raw.length()) + raw). // e.g. "A" -> "U+000A"
forEach(System.out::println);
}
}
}
用如下的命令可以编译 Verify.java 并运行其中的 main 方法。
javac Verify.java
java Verify
运行结果如下 ⬇️ 结果符合预期
Java 中一共有 25 个 white space character
这些 character 分别是 ⬇️
U+0009
U+000A
U+000B
U+000C
U+000D
U+001C
U+001D
U+001E
U+001F
U+0020
U+1680
U+2000
U+2001
U+2002
U+2003
U+2004
U+2005
U+2006
U+2008
U+2009
U+200A
U+2028
U+2029
U+205F
U+3000