stringtokenizer 是 java 1.0 引入的老式字符串分割工具,不支持正则、无法返回空字段、不可变遍历;自 java 1.4 起官方推荐用 string.split() 或 pattern.split(),仅适用于简单、干净输入的遗留或嵌入式场景。

StringTokenizer 是什么,现在还该用吗
它是个老派的字符串分割工具类,不支持正则、不能返回空字段、不可变遍历——Java 1.0 就有了,但自 Java 1.4 起,官方文档就明确建议优先用 String.split() 或 Pattern.split()。它没被废弃,但属于“能跑,不推荐”的类型。
适用场景非常窄:只做简单空格/逗号分隔,且确定输入干净(无连续分隔符、无首尾空白),又不想引入正则开销的嵌入式或遗留系统。
常见错误现象:NoSuchElementException 频发,因为 hasMoreTokens() 和 nextToken() 不是原子操作,多线程调用必崩;还有人误以为它会跳过空串,其实默认保留(除非显式设 returnDelims=false 且用双分隔符)。
怎么安全地替代 StringTokenizer
绝大多数情况下,String.split() 更直接、更可控:
立即学习“Java免费学习笔记(深入)”;
-
"a,,b".split(",")返回长度为 3 的数组:["a", "", "b"];而StringTokenizer默认会把中间的空串吞掉 - 需要忽略首尾空白?先
trim()再split(),比手动 while 循环调nextToken()清晰得多 - 要保留分隔符?用
Pattern.compile("(,)|(;)").splitAsStream(str)配合Matcher,StringTokenizer根本做不到 - 性能差异微乎其微:现代 JVM 对
split()优化很好,除非在极严苛的 GC 敏感场景,否则别预设“StringTokenizer 更快”
如果非得用 StringTokenizer,必须注意这三点
不是劝退,是真要用时的保命清单:
- 永远先检查
hasMoreTokens(),再调nextToken()—— 即使刚调过一次,也不能省 - 构造时明确传
returnDelims参数:new StringTokenizer("a,b,c", ",", true)才能拿到逗号本身;默认是false,分隔符直接丢弃 - 别把它当集合用:
StringTokenizer没有Iterator,无法和 for-each 兼容,强行包装容易出ConcurrentModificationException
split() 的坑比 StringTokenizer 还多?关键看你怎么填参数
String.split() 看似简单,但两个参数细节决定成败:
- 第一个参数是正则表达式,所以分隔符含
.、*、+等需转义:"file.txt".split("\."),写成"file.txt".split(".");会按“任意字符”切,结果是空数组 - 第二个参数
limit控制分割次数:"a:b:c:d".split(":", 2)得["a", "b:c:d"];设为负数(如-1)才保留末尾空串,否则"a::b:".split(":")结果是["a", "", "b"],最后那个空串没了 - 兼容性没问题:从 Java 1.4 到 21,语义稳定;但 Android API 26+ 才完全支持
split(regex, limit)的负数行为,旧版本慎用
真正复杂的分割逻辑(比如引号内不分割、跳过注释行),早该交给 Scanner 或专用 parser,别硬扛。










