4

As buffered reader is much faster than scanner class in case of inputting values from the user, however as observed in most of the Algorithm Competitions or in case of interviews there are often multiple integers on a single input line. Hence, it becomes easier to use Scanner Class -

    Scanner in=new Scanner(System.in);
    int a=in.nextInt();
    int b=in.nextInt();

In case of Buffered Reader, you will have to first input a line (as there is no option of readInt) and then parse the line according to number of integers on it -

    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]);

Although the input may be faster in latter case, won't the parsing take up much time to divide the obtained string into indiviual integers? Hence, in such case which one of the above is more optimal or faster?

Thank you.

user8321763
  • 149
  • 1
  • 11
  • 1
    If you manage to actually perceive the difference, then you have a completely different problem. – Fildor Sep 18 '17 at 14:19
  • The fastest way is probably to read a block of bytes into an array, iterate over each byte, and manually convert character sequences into integer values. This avoids having to allocate string objects and calling split() or using regexes. – Nayuki Sep 18 '17 at 14:22

2 Answers2

5

Very wrong approach: you are talking about user input. It absolutely doesn't matter how you process something that is provided on human time scale.

A human operates on "seconds", in some scenarios on "milli seconds".

Whereas the delta between a Scanner and a BufferedReader in terms of performance is probably in the range of micro seconds, maybe even nano seconds.

And even when we don't talk about a human person typing in content on the console (but using piping, like cat somefile | java Whatever) - you still have IO happening on a large scale. Your application will spent 99.99% of its time waiting for IO to happen. How the incoming strings are processed in the end simply doesn't matter.

In other words: you better spent your time on writing clean code, that gets the job done in a straight forward way that is easy to understand to its human readers. And then let the JIT do its magic.

As the question is specifically about processing "file based" input - go profile yourself. What I would do here:

  • create an abstraction layer that allows me to easily switch between different implementations
  • then I would start to benchmark different solutions (carefully read this to prepare for such activity)

You see, in the end both pieces of code will do very similar things. A scanner is still working on something, and you would have to dig into the corresponding source code for quite some time to understand potential differences between Scanner parsing and BufferedReader reading + manual parsing.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • The question suggested that the input might be from a text file, like a test case in a programming competition. – Nayuki Sep 18 '17 at 14:23
  • @Nayuki I reworked my answer to address that part as well. – GhostCat Sep 18 '17 at 14:24
  • 1
    Yes, I totally understand what you mean to say. However, my problem isn't against human inputs but the already designed code compilers and testcases. In my example, I have used two integers, but the testcases used by some of the code testers may range upto 10^5 inputs. Also, in such scenarios, the allowed time for execution is around 1 sec or even lesser. So, wouldn't it matter (time wise) to divide a string containing around 10^5 integers in order to split it up into String array of 10^5 size and then parse each value into integer. – user8321763 Sep 18 '17 at 14:28
  • @user8321763 See my updates then. Hope you find them helpful. – GhostCat Sep 18 '17 at 14:40
3

This is one of the cases when code clarity is more important than the speed.

It is easy to see that the code using Scanner goes strait to the point of what is going on, and reads very naturally.

On the other hand, the code using BufferedReader performs some additional tasks before doing what it is required to do (reading two integers from the input) so a reader of your code may spend a few seconds to see what is going on.

Of course, some error handling code missing from both implementations. For example, the second implementation needs to check that split returned exactly two items. If the first implementation omits all error checking, the caller would get a message saying that there's no integer in the input. The second implementation would get an index out of range exception, which would require additional research to see what is going on.

As far as the parsing goes, it has to happen in both cases, so you would end up spending about the same number of CPU cycles to process it.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523