java 快速io_java 最快的input (ACM) Java高效IO

java 最快的input

问题: Scanner 非常非常非常慢

使用Scanner来输入非常方便,但很慢. 使用 BufferedReader 和 StringTokenizer 会更快, 但是在比赛中没有时间打这么繁杂的代码. 我们是否可以让java在ACM中

用起来更加简便呢?

java的输入比C繁杂太多了 (如果你使用BufferedReader会更糟糕)

JavaC/C++

Scanner input =

new Scanner(System.in);

double x = input.nextDouble();

double x;

scanf("%lf",&x);

有多慢?

我测试从文件中读取 10,000,000个 int 或者 double. 用时时如下表. 我的运行环境是 Intel Core2 Duo 2.4GHz cpu, Windows XP Pro SP3, Sun JDK 6.0r22, 和GNU gcc 4.5.2.

表格1. 从文件中读取 10,000,000 int值用时

Input MethodTime (sec)

C scanf("%d", &arg)

3.78

Scanner.parseInt()

29.52

BufferedReader + inline Integer.parseInt

2.89

BufferedReader + Reader.nextInt method

3.01

表格2.从文件中读取 10,000,000 double值用时

Input MethodTime (sec)

C scanf("%lf", &arg)

11.9

Scanner.parseDouble()

66.86

BufferedReader + inline Double.parseDouble

3.06

BufferedReader + Reader.nextDouble method

3.14

列表1. 分别用Scanner 和 BufferedReader用以下示例代码来读取 。 我们分割输的一行为 string tokens,c因为一行可能包括

多个值。分割输入行来说, StringTokenizeris 比 string.split()快4倍以上.

/** 用Scanner读取指定个数的整数*/

static int scanInteger(int count) {

Scanner scanner = new Scanner(input);

int last = 0;

while (count-- > 0) {

last = scanner.nextInt();

}

return last;

}

/** 使用BufferedReader读取指定个数的整数 */

static int readIntegers(int count)

throws IOException {

BufferedReader reader = new BufferedReader(

new InputStreamReader(input) );

StringTokenizer tokenizer = new StringTokenizer("");

int last = 0;

while (count-- > 0) {

if (! tokenizer.hasMoreTokens() ) {

tokenizer = new StringTokenizer(reader.readLine());

}

last = Integer.parseInt(tokenizer.nextToken());

}

return last;

}

创建可重用代码

Java如何减轻读取输入的负担呢? Java和C/C++比较有如下优势: 更少语法错误, 也许更少逻辑错误, 更好的代码生成 和 在Eclipse中调试.

为了使java更容易使用, 让我们把输入代码放到一个单独的类吧. (你可以在源文件中放多个类, 前提是只有一个类是“public”的。) 我们可以复制粘贴 Reader 类到每一个ACM 编程任务中, 所以我们在竞赛中只要写一次。 当其他人在研究问题的时候,其中一个人就可以写好它。

列表2 只是其中一个例子. 如果你有更短,更有效的代码一定要告诉我. 我用了 StringTokenizer 代替 string.split() 因为StringTokenizer更快。 我使用了静态方法, 好处就是, 我们不必创建Reader的对象 , 并且使用默认访问权限(因为在同一个包下),所以就不用花时间打“public”。在我的测试中, 把输入方法放到一个单独的类中对速度基本没有影响 (有点惊讶)。但是对于余下的编程任务来说, 这会代码的提高可重用性和简便性,。

好像还是挺长的, 但是你只要打一次,以后可以就复制粘贴。

所以在你的 ACM 编程任务中, 你可以写这样的代码:

Reader.init( System.in );

double x = Reader.nextDouble();

int n = Reader.nextInt();

列表2. 读取int和double的可重用类。

/** 读取int和double的类 */

class Reader {

static BufferedReader reader;

static StringTokenizer tokenizer;

/** 调用这个方法来初始化reader,即InputStream*/

static void init(InputStream input) {

reader = new BufferedReader(

new InputStreamReader(input) );

tokenizer = new StringTokenizer("");

}

/** 获取下一段文本 */

static String next() throws IOException {

while ( ! tokenizer.hasMoreTokens() ) {

//TODO add check for eof if necessary

tokenizer = new StringTokenizer(

reader.readLine() );

}

return tokenizer.nextToken();

}

static int nextInt() throws IOException {

return Integer.parseInt( next() );

}

static double nextDouble() throws IOException {

return Double.parseDouble( next() );

}

}

翻译by kucoder

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值