
本文介绍如何使用正则表达式将 arraylist 中的每个英文字符串精确拆分为长度为 2 的子串(末尾不足两位时保留原样),适用于奇偶长度统一处理的分词场景。
在自然语言处理或自定义词法分析器(如 Tokenizer 类)中,常需将单词按固定宽度切片。题目要求:对 Reader 类生成的 Wlist(全大写英文单词列表),将每个字符串从左到右每两个字符切分为一个子串,无论原字符串长度是奇数还是偶数——这恰好对应“三段式”视觉分组(如 "teacher" → "te", "ac", "her";"cattle" → "ca", "tt", "le"),其本质是以步长 2 进行等宽切片,末段容纳剩余字符。
Java 中最简洁、高效的方式是使用正则表达式的 split() 配合边界断言(lookaround),而非手动计算索引或循环截取。核心正则表达式为:
"(?<=\\G..)(?=..)"
- \\G 表示上一次匹配结束的位置(或字符串开头);
- (?正向后查找(positive lookbehind):断言当前位置前恰好有两个字符,且这两个字符紧接在上一匹配之后;
- (?=..) 是正向前查找(positive lookahead):断言当前位置后至少还有两个字符;
- 二者组合,即在“每两个字符之后、且后面仍有至少两个字符”的位置进行分割。
⚠️ 注意:该正则不会在末尾产生空字符串,也无需额外处理奇偶逻辑——它天然适配所有长度。例如:
- "Printer"(7 字符)→ ["Pr", "in", "ter"]
- "Airport"(7 字符)→ ["Ai", "rp", "ort"]
- "Letter"(6 字符)→ ["Le", "tt", "er"]
✅ 正确实现 Tokenizer.splitString()
需修正原代码中的两个关键问题:
立即学习“Java免费学习笔记(深入)”;
- 错误使用 Arrays.toString(...) 将 String[] 转为 [a, b, c] 格式字符串,导致 SplList 存的是文本而非子串数组;
- 未导入 java.util.Arrays,且 split() 应作用于单个字符串,而非整个 ArrayList。
以下是修复后的专业级实现:
import java.util.*;
import java.util.stream.Collectors;
public class Tokenizer {
private final Reader rd = new Reader();
public List> splitString() {
List wordList = rd.getWord(); // 获取大写单词列表
List> result = new ArrayList<>();
for (String word : wordList) {
String[] parts = word.split("(?<=\\G..)(?=..)");
result.add(Arrays.asList(parts)); // 转为不可变子列表便于后续处理
}
// 可选:打印验证
result.forEach(parts -> System.out.println(parts));
return result;
}
}
? 进阶建议:若需返回扁平化的 ArrayList(所有子串合并为单层列表),可改用流式操作:public ArrayList splitStringFlat() { return rd.getWord().stream() .flatMap(word -> Arrays.stream(word.split("(?
? 关键注意事项
- 此正则仅适用于 ASCII 字母字符串;含 Unicode(如中文、emoji)或代理对(surrogate pairs)时需改用 codePointCount + 手动切片;
- 空字符串或长度
- 若业务强制要求必须三段(如 "a" → ["a", "", ""]),则需额外补零逻辑,但本题语义明确为“自然分组”,无需填充。
综上,利用 (?










