在 Java 的一行中对多个整数使用 BufferedReader 而不是 Scanner Class 是否最佳?
Is it optimal to use BufferedReader instead of Scanner Class for multiple integers on a single line in Java?
As buffered reader 在用户输入值的情况下比 scanner class 快得多,但是正如在大多数算法竞赛或面试中观察到的那样,通常有多个整数在单个输入线上。因此,使用 Scanner Class -
变得更容易
Scanner in=new Scanner(System.in);
int a=in.nextInt();
int b=in.nextInt();
如果是Buffered Reader,则必须先输入一行(因为没有readInt选项),然后根据其上的整数个数解析该行-
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int a,b;
String line = br.readLine();
String[] strs = line.trim().split("\s+");
a=Integer.parseInt(strs[0]);
b=Integer.parseInt(strs[1]);
虽然后一种情况下输入可能会更快,但是解析会不会花费很多时间将得到的字符串分成一个个整数?
因此,在这种情况下,以上哪一项更优或更快?
谢谢。
非常错误的方法:你在谈论用户输入。 如何处理人类时间尺度上提供的内容绝对无关紧要。
人类在 "seconds" 上操作,在某些情况下 "milli seconds"。
而就 性能 而言,Scanner 和 BufferedReader 之间的差异可能在 micro 秒的范围内,甚至可能 纳米秒.
即使我们不谈论人类在控制台上输入内容(但使用 管道,如 cat somefile | java Whatever
)——你仍然有 IO 大规模发生。您的应用程序将花费 99.99% 的时间等待 IO 发生。传入的字符串最终如何处理根本无关紧要。
换句话说:你最好把时间花在编写 干净 代码上,这样可以以一种易于理解的直接方式完成工作 human 读者。然后让 JIT 发挥它的魔力。
因为这个问题是专门关于处理 "file based" 输入的 - 你自己去 profile 。我会在这里做什么:
- 创建一个抽象层,让我轻松在不同的实现之间切换
- 那我就开始benchmark不同的解决方案(仔细阅读this为这样的activity做准备)
你看,最终两个段代码会做非常相似的事情。 Scanner 还在做 something,你必须花相当长的时间去研究相应的源代码,才能理解 Scanner 解析和 BufferedReader 读取 + 手动解析之间的潜在差异。
这是代码清晰度比速度更重要的情况之一。
很容易看出使用 Scanner
的代码直截了当,读起来很自然。
另一方面,使用 BufferedReader
的代码在执行需要执行的操作(从输入中读取两个整数)之前会执行一些额外的任务,因此 reader 的代码可能会花费几秒钟看看发生了什么。
当然,两种实现都缺少一些错误处理代码。例如,第二个实现需要检查 split
是否恰好返回了两个项目。如果第一个实现忽略所有错误检查,调用者将收到一条消息,指出输入中没有整数。第二种实现会得到一个索引超出范围的异常,这将需要额外的研究来了解发生了什么。
就解析而言,它必须在两种情况下都发生,因此您最终会花费大约相同数量的 CPU 周期来处理它。
As buffered reader 在用户输入值的情况下比 scanner class 快得多,但是正如在大多数算法竞赛或面试中观察到的那样,通常有多个整数在单个输入线上。因此,使用 Scanner Class -
变得更容易 Scanner in=new Scanner(System.in);
int a=in.nextInt();
int b=in.nextInt();
如果是Buffered Reader,则必须先输入一行(因为没有readInt选项),然后根据其上的整数个数解析该行-
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int a,b;
String line = br.readLine();
String[] strs = line.trim().split("\s+");
a=Integer.parseInt(strs[0]);
b=Integer.parseInt(strs[1]);
虽然后一种情况下输入可能会更快,但是解析会不会花费很多时间将得到的字符串分成一个个整数? 因此,在这种情况下,以上哪一项更优或更快?
谢谢。
非常错误的方法:你在谈论用户输入。 如何处理人类时间尺度上提供的内容绝对无关紧要。
人类在 "seconds" 上操作,在某些情况下 "milli seconds"。
而就 性能 而言,Scanner 和 BufferedReader 之间的差异可能在 micro 秒的范围内,甚至可能 纳米秒.
即使我们不谈论人类在控制台上输入内容(但使用 管道,如 cat somefile | java Whatever
)——你仍然有 IO 大规模发生。您的应用程序将花费 99.99% 的时间等待 IO 发生。传入的字符串最终如何处理根本无关紧要。
换句话说:你最好把时间花在编写 干净 代码上,这样可以以一种易于理解的直接方式完成工作 human 读者。然后让 JIT 发挥它的魔力。
因为这个问题是专门关于处理 "file based" 输入的 - 你自己去 profile 。我会在这里做什么:
- 创建一个抽象层,让我轻松在不同的实现之间切换
- 那我就开始benchmark不同的解决方案(仔细阅读this为这样的activity做准备)
你看,最终两个段代码会做非常相似的事情。 Scanner 还在做 something,你必须花相当长的时间去研究相应的源代码,才能理解 Scanner 解析和 BufferedReader 读取 + 手动解析之间的潜在差异。
这是代码清晰度比速度更重要的情况之一。
很容易看出使用 Scanner
的代码直截了当,读起来很自然。
另一方面,使用 BufferedReader
的代码在执行需要执行的操作(从输入中读取两个整数)之前会执行一些额外的任务,因此 reader 的代码可能会花费几秒钟看看发生了什么。
当然,两种实现都缺少一些错误处理代码。例如,第二个实现需要检查 split
是否恰好返回了两个项目。如果第一个实现忽略所有错误检查,调用者将收到一条消息,指出输入中没有整数。第二种实现会得到一个索引超出范围的异常,这将需要额外的研究来了解发生了什么。
就解析而言,它必须在两种情况下都发生,因此您最终会花费大约相同数量的 CPU 周期来处理它。