9

My professor tends to do the following to get a number from the user:

Scanner scanner = new Scanner(System.in);
Integer.parseInt(scanner.nextLine());

What are the benefits as opposed to simply doing scanner.nextInt() ?

java.util.Scanner.java has the following in it:

public int nextInt() {
    return nextInt(defaultRadix);
}

public int nextInt(int radix) {
    // Check cached result
    if ((typeCache != null) && (typeCache instanceof Integer)
        && this.radix == radix) {
        int val = ((Integer)typeCache).intValue();
        useTypeCache();
        return val;
    }
    setRadix(radix);
    clearCaches();
    // Search for next int
    try {
        String s = next(integerPattern());
        if (matcher.group(SIMPLE_GROUP_INDEX) == null)
            s = processIntegerToken(s);
        return Integer.parseInt(s, radix);
    } catch (NumberFormatException nfe) {
        position = matcher.start(); // don't skip bad token
        throw new InputMismatchException(nfe.getMessage());
    }
}

As I see it, Scanner calls Integer.parseInt() itself as well, on top of additional hocus pocus. Are there significant performance gains in doing simply Integer.parseInt(scanner.nextLine()) ? Are there on the other hand any drawbacks?

How about when scanning through a file with significant amount of data, and not a user input?

Olavi Mustanoja
  • 1,975
  • 2
  • 18
  • 30

3 Answers3

15

There are 2 observations :

  1. Using myScannerInstance.nextInt() leaves behind a new line character. So, if you call nextLine() after nextInt(), the nextLine() will read the new line character instead of the actual data. Consequently, you will have to add another nextLine() after the nextInt() to gobble up that dangling new-line character. nextLine() doesn't leave behind a new line character.

code :

int age=myScannerInstance.nextInt();
String name = myScannerInstance.nextLine();// here the actual name will not be read. The new line character will be read.
  1. nextInt() will again go back to the underlying stream and read. IO calls take time (expensive). It will do lot of checks to get the next integer. nextLine() will do those checks only once. So, if you call nextLine() once and read 5 integers (as a single line String), split them and parse them as integers (using Integer.parseInt()), it will be faster and more efficient than reading each int individually.

Using nextLine() + parseInt() will give you enormous performance benefit when you are running a very large loop.

Usage :

Using nextInt() gives you an additional advantage wherein you will get an exception if the input text is not an integer. example 123 is accepted.. 123sdsa will throw an InputMismatchException. So, you can catch it and handle it appropriately.

Using nextLine() will read the entire line, so, it will read the entire String sada1231 and then fail with NumberFormatException if it cannot parse the String as a number. You will have to handle that exception.

Generally, one nextLine() / nextInt() call won't make much of a difference. If you have a loop or if you are reading lot of data, then using readLine() with parseInt() will be very efficient.

Ashbrak
  • 3
  • 3
TheLostMind
  • 34,842
  • 11
  • 64
  • 97
  • Worth mentioning that `nextInt()` won't consume the next token if it fails to parse. – shmosel Nov 20 '17 at 18:02
  • 1
    I found some exactly opposite behavior about this when I was solving below problem. https://www.hackerrank.com/challenges/maximum-element/problem, when I used nextLine() with parseInt() few test cases got timeout error, but when I used scanner.nextInt() those test cases passed. Any comments on this to clear the idea ? – Nilesh Pharate Jan 11 '18 at 18:21
  • nice and clean explanation. – koo Oct 27 '19 at 12:14
0

nextInt() reads a number, but doesn’t consume line separator. While nextLine() reads the String and consumes the new-line character. According to Java Docs:

… This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.

In other words when you enter a number then press Enter, input.nextInt() consumes only the number, not the "end of line", primitive data types like int, double etc does not consume "end of line", due which this "end of line" remain in buffer ane When input.next() executes, it consumes the "end of line" from buffer from the first input. So you professor is trying to get to the next line after he reads the user input. You have to look at the logic of his codes only then you can understand it.

Payam
  • 461
  • 2
  • 16
0

I also used to face this problem often. So i use to code like this..

public static void main(String[] args) {
    Scanner key= new Scanner(System.in);
    String name;
    int    age;
    age = key.nextInt();
    key.nextLine();
    name = key.nextLine();  //to carry the new line character left behind nextInt()
    System.out.println("Age : "+age);
    System.out.println("Name: "+name);
}

here as the key.nextInt() leaves a new line character we are using key.nextLine() to carry the new Line character and then move to the nextline where the actual data is present. As we discussed above using Integer.parseInt() will be more efficient than using nextInt(). But this is also one of the way to code to overcome the problem.

Sanoaf
  • 21
  • 3
  • Adding a `nextLine` only to consume the new line character might make the code seem confusing or incorrect. `nextLine` is a function that **returns** the current line, using it purely to advance the position in the scanner seems counter-intuitive. – Bernhard Barker Jun 07 '17 at 16:41
  • The accepted answer posted 3 years earlier already mentions this, I'm not sure what this answer adds beyond that. – Bernhard Barker Jun 07 '17 at 16:42