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?
There are 2 observations :
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.
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.
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.
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.
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.
public class Solution {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int i = scan.nextInt();
double d = scan.nextDouble();
scan.nextLine();
String s = scan.nextLine();
scan.close();
System.out.println("String: " + s);
System.out.println("Double: " + d);
System.out.println("Int: " + i);
}
}
Related
For avoiding any unwanted character which has been entered in console like \n
we use nextInt() or nextLine() etc.
But in these cases actually the control is going a step ahead leaving the unwanted string or something like this.
But I want to delete or flush out the memory of buffer in which other unwanted data is taken by the system.
For example -->
Scanner scan=new Scanner(System.in);
scan.nextInt();
scan.nextline();//this statement will be skipped
because the system is taking \n as a line next to the integer given as input.
In this case without using scan.nextLine() I want to simply clear/flush out the buffer memory where the \n was stored.
Now please tell me how to delete the input buffer memory in java
Thank you. :)
You can use this to clear all existing data in the buffer:
while(sc.hasNext()) {
sc.next();
}
If you are only doing this to remove the newline (\n) characters from the input, you can use:
while(sc.hasNext("\n")) {
sc.next();
}
If the goal is to only read integers and skip any other characters, this would work:
while(sc.hasNext() && !sc.hasNextInt()) {
sc.next();
}
you can simply use one more scan.nextLine() before taking the string as input.
Scanner scan = new Scanner(System.in);
int x = scan.nextInt();
scan.nextLine(); // clears the input buffer
String s = scan.nextLine(); // this statement won't get skip
Reference : the solution to this hackerrank question uses the same idea which I provided
I have following code and am facing a problem if I use System.in.read() before Scanner.
Then the cursor moves at the end by skipping nextLine() function.
import java.util.Scanner;
public class InvoiceTest{
public static void main(String [] args) throws java.io.IOException {
System.out.println("Enter a Charater: ");
char c = (char) System.in.read();
Scanner input = new Scanner(System.in);
System.out.println("Enter id No...");
String id_no = input.nextLine();
System.out.println("Charater You entered "+ c +" Id No Entered "+ id_no);
}
}
You are not consuming the newline character upon entering your character(System.in.read()) thus the input.nextLine() will consume it and skip it.
solution:
consume the new line character first before reading the input of for the id.
System.out.println("Enter a Charater: ");
char c = (char) System.in.read();
Scanner input = new Scanner(System.in);
System.out.println("Enter id No...");
input.nextLine(); //will consume the new line character spit by System.in.read()
String id_no = input.nextLine();
System.out.println("Charater You entered "+c+" Id No Entered "+id_no);
}
EJP comments thus:
Don't mix System.in.read() with new Scanner(System.in). Use one or the other.
Good advice!
So why is it a bad idea to mix reading from the stream and using Scanner?
Well, because Scanner operations will typically read ahead on the input stream, keeping unconsumed characters in an internal buffer. So if you do a Scanner operation followed by a call to read() on the stream, there is a good chance that the read() will (in effect) skip over characters. The behaviour is likely to be confusing and unpredictable ... and dependent on where the input characters are actually coming from.
My program is to enter a substring and return all the books based upon the search.i want to ask the user again to search again from the same records.The code is not asking for the user input for the second time.Kindly help
boolean runnable=true;
while(runnable)
{
System.out.println("\n\nInput Books you wish for search");
String search;
search=br.nextLine();
System.out.println("\n\nBooks by your search");
for(int i=0;i<noOfrecords;i++)
{
if(books[i].toLowerCase().contains(search.toLowerCase()))
{
System.out.println(books[i]);
}
}
System.out.println("\n\nMore Books");
for(int i=0;i<noOfrecords;i++)
{
if(!(books[i].toLowerCase().contains(search.toLowerCase())))
{
System.out.println(books[i]);
}
}
System.out.println("do you wish to search again from the same records?? (y/n)");
char searchagain=br.next().charAt(0);
if(searchagain!='y')
{
runnable=false;
}
else if(searchagain=='y')
{
runnable=true;
}
}
I am sure that you have an extra unconsumed new line character in your buffer. Consume it by adding a line at the end of the while loop after else-if
else if(searchagain=='y')
{
runnable=true;
}
br.nextLine();
When you hit enter after keying the first input, Scanner.nextLine() advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. so, the line seperator \n is still in the buffer, which is been consumed while iterating the loop for the second time.we need to consume it purposefully by invoking br.nextLine(); at the end of the while loop and leave the new line character \n in air and go for second loop for fresh input. This will make it to stop and get the input for the second time.
Let me explain you in a simple way. Your program asks for
Input Books you wish for search
Now, you give Effective Java and press enter. This would become
EffectiveJava\n
\n (unconsumed char) in the end of your input will not be consumed by br.nextLine(). So, we need to explicitly get rid of it at the end of while loop. so, that \n will not be consumed by the br.nextLine() during the second loop and it will ask for your input
Because you are not able to read single character from console - System.in because new bytes are available in stream after Enter key is pressed.
Can be useful:
http://sourceforge.net/projects/javacurses/
http://jline.sourceforge.net/
I made little changes in your code.
public void searchMethod(List<String> books){
Scanner scanner = new Scanner(System.in);
System.out.println("\n\nInput Books you wish for search");
//this code is executed when books is null, so first time you can invoke that method passing as argument simply null.
if(books == null){
while(scanner.hasNext())
books.add(scanner.nextLine());
}
System.out.println("\n\nBooks by your search");
for(String book : books)
{
if(book.toLowerCase().contains(search.toLowerCase()))
{
System.out.println(book);
}
}
System.out.println("\n\nMore Books");
for(String book:books)
{
if(!(book.toLowerCase().contains(search.toLowerCase())))
{
System.out.println(book);
}
}
System.out.println("do you wish to search again from the same records?? (y/n)");
char searchagain=scanner.nextLine();
if(!searchagain.equals("y"))
{
return;
}
else if(searchagain.equals("y"))
{
searchMethod(books);
}
}
}
change next().charAt(0) to nextLine().charAt(). it will work.i think reason for this is next() sperates the token by spaces and read the token one by one from the buffer and stay at the line. when next() reaches the end of line and if u call nextLine(), then nextLine() encounter the end of line and nextLine() return blank line.
char searchagain = br.next().charAt(0);
to
char searchagain = br.nextLine().charAt(0);
The problem is I cant read the variable input with next() cause when I try to split (.split" ") every whitespace then the array just get the first two words I type so I had to use keyboard.nextLine() and the splitting process works the way it should work and I get all the words in the array but the problem is that If I use nextLine() then I have to create another keyboard object to read the first variable (answer) and that is the only way I can make it work here is the code
Scanner keyboard=new Scanner(System.in);
Scanner keyboard2=new Scanner(System.in);//just to make answer word
int answer=keyboard.nextInt();//if I don't use the keyboard2 here then the program will not work as it should work, but if I use next() instead of nextLine down there this will not be a problem but then the splitting part is a problem(this variable counts number of lines the program will have).
int current=1;
int left=0,right=0,forward=0,back=0;
for(int count=0;count<answer;count++,current++)
{
String input=keyboard.nextLine();
String array[]=input.split(" ");
for (int counter=0;counter<array.length;counter++)
{
if (array[counter].equalsIgnoreCase("left"))
{
left++;
}
else if (array[counter].equalsIgnoreCase("right"))
{
right++;
}
else if (array[counter].equalsIgnoreCase("forward"))
{
forward++;
}
else if (array[counter].equalsIgnoreCase("back"))
{
back++;
}
}
}
}
Thanks :)
Put keyboard.nextLine() after this line:
int answer=keyboard.nextInt();
This is a common problem that usually happens when you use nextLine() method after nextInt() method of Scanner class.
What actually happens is that when the user enters an integer at int answer = keyboard.nextInt();, the scanner will take the digits only and leave the new-line character \n. So you need to do a trick by calling keyboard.nextLine(); just to discard that new-line character and then you can call String input = keyboard.nextLine(); without any problem.
sry about my english :)
Im new to Java programming and i have a problem with Scanner. I need to read an Int, show some stuff and then read a string so i use sc.nextInt(); show my stuff showMenu(); and then try to read a string palabra=sc.nextLine();
Some one told me i need to use a sc.nextLine(); after sc.nextInt(); but i dont understand why do you have to do it :(
Here is my code:
public static void main(String[] args) {
// TODO code application logic here
Scanner sc = new Scanner(System.in);
int respuesta = 1;
showMenu();
respuesta = sc.nextInt();
sc.nextLine(); //Why is this line necessary for second scan to work?
switch (respuesta){
case 1:
System.out.println("=== Palindromo ===");
String palabra = sc.nextLine();
if (esPalindromo(palabra) == true)
System.out.println("Es Palindromo");
else
System.out.println("No es Palindromo");
break;
}
}
Ty so much for your time and Help :D
nextInt() only reads in until it's found the int and then stops.
You have to do nextLine() because the input stream still has a newline character and possibly other non-int data on the line. Calling nextLine() reads in whatever data is left, including the enter the user pressed between entering an int and entering a String.
When you input a value (whether String, int, double, etc...) and hit 'enter,' a new-line character (aka '\n') will be appended to the end of your input. So, if you're entering an int, sc.nextInt() will only read the integer entered and leave the '\n' behind in the buffer. So, the way to fix this is to add a sc.nextLine() that will read the leftover and throw it away. This is why you need to have that one line of code in your program.