为何Scanner转换输入为二维char数组耗时过长?
优化Scanner读取超大网格输入的性能
针对你遇到的Scanner读取10000×10000网格时性能极差的问题,核心原因是Scanner默认的输入缓冲区过小,加上逐个charAt()的循环累积了大量方法调用开销。以下是针对必须使用Scanner的场景的优化方案:
优化方案
1. 增大Scanner的输入缓冲区
Scanner默认依赖的InputStreamReader缓冲区很小(通常是8KB),处理超大输入时会频繁触发IO操作,严重拖慢速度。用BufferedReader包装System.in并设置大缓冲区(比如1MB),再传给Scanner,能大幅减少IO次数。
2. 替换逐字符遍历为一次性转char数组
原代码中内层循环逐个调用charAt(j),1e8次的方法调用会带来可观的开销。直接使用String.toCharArray()一次性把整行转为char数组,再批量复制到二维数组中,能显著减少耗时。
优化后的代码
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Scanner; public static void main(String[] args) { // 配置1MB大小的缓冲区,可根据需求调整(比如2MB) Scanner input = new Scanner(new BufferedReader(new InputStreamReader(System.in), 1024 * 1024)); int rows = input.nextInt(); int cols = input.nextInt(); // 跳过nextInt()后遗留的换行符,避免读取空行 input.skip("\n"); char[][] seaCard = new char[rows][cols]; for(int i = 0; i < rows; i++){ String thisRow = input.nextLine(); // 一次性转char数组,替代逐个charAt char[] rowChars = thisRow.toCharArray(); // 批量复制到二维数组,比逐个赋值更高效 System.arraycopy(rowChars, 0, seaCard[i], 0, cols); } input.close(); }
额外说明
- 如果输入的每行没有空格,也可以用
input.next()替代input.nextLine(),但核心优化还是缓冲区的配置,这对超大输入的性能提升最明显。 - 10000×10000的网格需要占用约100MB内存(char占2字节),确保JVM的堆内存足够(可通过
-Xmx256m参数调整)。
内容的提问来源于stack exchange,提问作者Jock
相关产品推荐
相关产品推荐

