一、中文文字在Java中的存储原理
Java采用UTF-16编码存储字符,每个字符占用2字节(16位)。对于基本多语言平面(BMP)内的字符(如常用汉字),可直接用char类型表示;而辅助平面字符(如部分生僻字)需用int类型或String的codePointAt()方法处理。这种编码方式决定了遍历中文时需注意字符与代码点的区别。
示例:判断字符是否为BMP内中文
public static boolean isBasicChinese(char c) {return c >= '\u4e00' && c <= '\u9fa5'; // 常用汉字范围}
二、基础遍历方法:字符数组与循环
1. 使用toCharArray()遍历
将字符串转为字符数组后遍历,适合处理BMP内字符。
String text = "你好世界";for (char c : text.toCharArray()) {System.out.println(c); // 输出每个字符}
局限性:无法直接处理辅助平面字符(如𠮷,U+20BB7),会拆分为两个char。
2. 代码点遍历(解决辅助平面问题)
通过String.codePointAt()和Character.charCount()正确处理所有Unicode字符。
String text = "𠮷"; // 辅助平面字符for (int i = 0; i < text.length(); ) {int codePoint = text.codePointAt(i);System.out.println(Character.toChars(codePoint));i += Character.charCount(codePoint); // 跳过1或2个char}
三、正则表达式匹配中文
1. 匹配连续中文
使用正则[\u4e00-\u9fa5]+匹配连续中文片段。
String text = "Hello 你好,世界!";Pattern pattern = Pattern.compile("[\\u4e00-\\u9fa5]+");Matcher matcher = pattern.matcher(text);while (matcher.find()) {System.out.println(matcher.group()); // 输出"你好"和"世界"}
2. 扩展中文范围(含标点)
若需包含中文标点,可扩展正则:
Pattern.compile("[\\u4e00-\\u9fa5\\u3000-\\u303F\\uFF00-\\uFFEF]+");
四、Stream API实现函数式遍历
Java 8+的Stream API提供更简洁的遍历方式。
1. 基础字符流
String text = "Java处理中文";text.chars().forEach(c -> System.out.println((char)c));
2. 代码点流(完整Unicode支持)
IntStream codePoints = text.codePoints();codePoints.forEach(cp -> System.out.println(Character.toChars(cp)));
五、性能优化与注意事项
1. 字符串拼接性能
频繁拼接中文时,优先使用StringBuilder:
StringBuilder sb = new StringBuilder();for (char c : text.toCharArray()) {sb.append(c).append("-"); // 高效拼接}
2. 大文本处理建议
- 分块读取:处理GB级文本时,按行或固定大小分块。
- 并行流:对无依赖操作使用
parallelStream()。text.codePoints().parallel().forEach(...);
3. 编码问题排查
- 明确文件编码(如UTF-8),避免
IOException: Invalid byte sequence。 - 使用
Charset.defaultCharset()检查默认编码。
六、实际应用场景示例
1. 中文分词预处理
遍历文本并标记中文词边界:
String text = "自然语言处理";boolean inChinese = false;for (int i = 0; i < text.length(); ) {int cp = text.codePointAt(i);if (isChineseCodePoint(cp)) {if (!inChinese) System.out.print("|"); // 词边界inChinese = true;} else {inChinese = false;}i += Character.charCount(cp);}// 输出: |自|然|语|言|处|理|
2. 敏感词过滤
结合遍历与哈希集合实现高效过滤:
Set<String> sensitiveWords = Set.of("暴力", "色情");String text = "这是一段包含暴力的文本";for (int i = 0; i < text.length(); ) {int end = i + Math.min(2, text.length() - i); // 最多检查2个字符的词String substring = text.substring(i, end);if (sensitiveWords.contains(substring)) {System.out.println("检测到敏感词: " + substring);}i += Character.charCount(text.codePointAt(i));}
七、进阶技巧:NIO与内存映射
处理超大中文文本时,使用FileChannel和内存映射提升性能:
try (FileChannel channel = FileChannel.open(Paths.get("large.txt"))) {MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());CharBuffer charBuffer = StandardCharsets.UTF_16.decode(buffer);while (charBuffer.hasRemaining()) {char c = charBuffer.get();if (isBasicChinese(c)) {System.out.print(c);}}}
八、总结与最佳实践
- 编码统一:始终以UTF-8/UTF-16处理中文,避免乱码。
- 方法选择:
- 简单场景:
toCharArray()+ 循环。 - 完整Unicode支持:代码点遍历。
- 函数式需求:Stream API。
- 简单场景:
- 性能关键:
- 大文本优先NIO。
- 避免字符串拼接时创建过多对象。
- 扩展性:正则表达式适合灵活匹配,但性能低于直接遍历。
通过掌握上述方法,开发者可高效处理从简单到复杂的中文文本操作,兼顾正确性与性能。