scanner适合流式处理,内存恒定且支持类型转换;stringtokenizer预加载全部token,内存占用高但取值快;split()适用于单行短文本,简洁高效。

处理大量文本时,Scanner 和 StringTokenizer 的效率和内存表现差异明显,关键不在“哪个更好”,而在于“用在哪”。它们的设计目标不同,直接对比性能容易误判场景。
核心机制差异决定适用边界
StringTokenizer 在初始化时就把整个字符串按分隔符切好,所有 token 全部加载进内存,后续调用 nextToken() 只是顺序返回已存好的引用。这带来两个结果:
- 首次构造稍慢(需预扫描),但后续取 token 极快(O(1))
- 内存占用与原始字符串长度正相关,token 越多、越长,开销越大
- 支持 countTokens(),无需遍历即可知道总数量
Scanner 则完全不同:它不缓存 token,只保存分隔逻辑(比如正则或字符集)和当前读取位置。每次 next() 都要现场匹配、截取、转换——相当于边走边拆。
- 单次取 token 较慢(尤其用正则分隔时)
- 内存占用极低,基本恒定,与输入规模无关
- 无法提前获知 token 总数,必须遍历一遍才能统计
海量变量流场景下的实际取舍
所谓“海量变量流”,通常指从文件、网络或标准输入持续读入的长文本,例如日志行、CSV 流、配置块。这时重点不是单行解析快慢,而是整体吞吐与资源稳定性。
- 用 StringTokenizer 解析一个 50MB 的文件?会瞬间申请数百 MB 内存,极易触发 GC 甚至 OOM
- Scanner 配合 BufferedReader(推荐组合)可逐行读取、逐行 tokenize,内存峰值稳定在几 KB 级别
- 若变量流中含混合类型(如数字、布尔、日期),Scanner 的 nextInt()、nextBoolean() 等方法天然适配,StringTokenizer 返回全是 String,还需手动转换
替代方案:String.split() 常被低估
对单行短文本(如参数解析、简单 CSV 行),String.split() 往往是更优解:
- 比 StringTokenizer 更简洁(返回 String[],不用 while + nextToken)
- 比 Scanner 更轻量(无对象状态、无正则引擎开销)
- 若分隔符固定(如逗号),性能接近 StringTokenizer;若用正则,可预编译 Pattern 提升复用效率
- 注意:split() 每次调用都重新编译正则,高频调用建议缓存 Pattern 实例
结论:按数据形态选工具
大文件流式处理 → Scanner + BufferedReader 是稳态首选;单行结构化小数据 → split() 最简高效;遗留系统或极端性能敏感且内存充足 → StringTokenizer 可用,但现代项目基本无需主动选用。










