12

I understand what is Scanner good for, and also when to use Scanner and when BufferedReader. I read a different, yet in some therm similar question Scanner vs. BufferedReader

Why is Scanner so slow when I read from the input? I assume it has to do with that there is a small buffer in Scanner, but here I am lost. The original problem is from, Codechef , but I am not interested in that solution.

Here is a code example with a given input: Input:

  • 7 3
  • 1
  • 51
  • 966369
  • 7
  • 9
  • 999996
  • 1

And the code

import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] s = br.readLine().split(" "); 
        int numberOfLines = Integer.parseInt(s[0]);
        int divideNumber = Integer.parseInt(s[1]);
        int count = 0;

        for (int i = 0; i < numberOfLines; i++) {
            String number = br.readLine();
            if (number.length() < 11) {
                int num = Integer.parseInt(number);
                if (num % divideNumber == 0) {
                    count++;
                }
            } 
        }
        System.out.println(count);
    }
}

If I read the same code with scanner it is slow.

Gábor Csikós
  • 2,283
  • 6
  • 28
  • 52
  • [`Scanner`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/util/Scanner.java#Scanner.hasNextLine%28%29) is based on regular expression parsing, [`BufferedReader`](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/io/BufferedReader.java#BufferedReader.readLine%28boolean%29) does simple checks on `char`s – zapl Feb 15 '14 at 12:54
  • 2
    If you want to get a really fast solution to that problem you would btw have to skip `BufferedReader` & `Integer.parseInt()` completely. It's still creating an unnecessary temporary `String` object before you can convert it into an `int` and that takes a lot of time compared to building `int` directly from the stream. – zapl Feb 15 '14 at 13:37
  • I came here because I was having to read a CSV file with ~13M lines. Used Scanner first and it took well over 2 hours. Changed to BufferedReader and it took a few minutes. On a modern MacBook Pro. I understood that there would be speed differences but that they were so big baffled me. EDIT: Second time running directly afterwards it took only a few seconds. Maybe the JIT is kicking in. – Robert Sjödahl May 08 '21 at 07:46

5 Answers5

10

Upper-level classes/methods are generally slower than lower-level classes/methods.
In the same way you could ask why is searching with regular expressions slower than
searching with String.indexOf(). Actually I've seen such questions here on SO.

The more specialized your class/method is, the better it can perform.
It does e.g. just 1 simple thing but does it quickly and efficiently.
More general classes/methods do e.g. 10-20 different things, so they
are more powerful but due to this they are slower.

I am speaking in general here, I haven't compared Scanner and BufferedReader myself.

peter.petrov
  • 34,474
  • 11
  • 63
  • 118
2

Beside what has been already said Scanner focus is being a Swiss army knife, it is quite more complex and in simple cases covered by BufferedReader that extra gadgets burden it. It's like sending an aircraft carrier to kill a rat.

aalku
  • 2,720
  • 1
  • 18
  • 41
0

Scanner inbuilt functions parse the tokens where the BufferedReader just read the input.There is overhead of parsing tokens...

Devavrata
  • 1,655
  • 13
  • 26
  • This is true, but If I read the example code whit Scanner the token would be the whole line, according to the documentation: "A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods." – Gábor Csikós Feb 15 '14 at 12:42
  • So it is only so slow because it needs that extra action for a token? – Gábor Csikós Feb 15 '14 at 12:59
  • Check this [link](http://en.allexperts.com/q/Java-1046/2009/2/Difference-Scanner-Method-Buffered.htm) – Devavrata Feb 15 '14 at 13:06
0

As mentioned in your question where you state a different question. The scanner performs extra tasks such as parsing integers and characters. The buffered reader reads raw input. What it reads is what it gives.

Hope I helped,

Jarod

TheBrenny
  • 519
  • 2
  • 17
0

Some highly voted hints why Scanner is slower can be found in Scanner vs. BufferedReader.

This performance difference may be critical in some cases like competitive programming. Therefore Codeforces has numerous posts with custom faster input parsers like here, here (with benchmark) and here.

Vadzim
  • 21,258
  • 10
  • 119
  • 142