为何在线评测平台中,try-with-resources包裹的Java Scanner比BufferedReader内存占用更低?
为什么
try-with-resources包裹的Scanner比BufferedReader峰值内存更低? 针对你在Codeforces遇到的这个反直觉现象,核心原因可以从这几点拆解:
- 默认缓冲区大小差异:
BufferedReader默认采用8192字节的缓冲区,而Scanner内部封装的BufferedReader默认缓冲区仅1024字节。如果输入数据没有填满大缓冲区,BufferedReader的闲置内存块会直接拉高峰值占用,小缓冲区反而更适配竞赛场景下的零散输入。 - 资源回收时机不同:
try-with-resources会在代码块结束后立即触发Scanner的关闭逻辑,连带释放底层的IO资源和临时对象;如果你的BufferedReader是手动管理的(未放入try-with-resources),资源释放可能延迟到GC的下一轮周期,导致内存快照捕捉到更高的峰值。 - 分词实现的内存开销:很多人用
BufferedReader时会配合split()做分词,这会生成大量临时字符串数组和对象;而Scanner的正则分词逻辑是流式处理,处理完的数据会及时释放临时对象,反而减少了内存驻留。 - JVM峰值统计的误差:Codeforces的内存统计是运行时的峰值快照,
Scanner的对象生命周期更短,可能在快照前就被GC回收,而BufferedReader的关联对象可能还在存活队列中,导致统计值偏高。
可以通过以下方式验证:
- 给
BufferedReader指定1024字节的缓冲区,再对比内存:try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in), 1024)) { // 读取逻辑 } - 把
BufferedReader也放进try-with-resources,确保资源及时释放。 - 替换
split()为StringTokenizer处理输入,减少临时对象生成。
内容的提问来源于stack exchange,提问作者Atom Eve
相关产品推荐
相关产品推荐

