3

I'm practicing HashSet from Java book by Cay S. Horstmann and Gary Cornell and I think there's a mistake in example code on page 687. We have a Scanner importing words to HashSet and it looks like this (I removed some unneeded code to make a problem more visible):

Set<String> words = new HashSet<String>();
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
    String word = in.next();
    words.add(word);
}

The problem is there's no way stop this loop. Or maybe there's something I'm missing?

To stop the loop I've added another static helper method:

public static boolean isStop(Scanner in) {
    if (in.next().equals("stop")) {
        return true;
    }
    return false;
}

And now the main code looks like this:

Set<String> words = new HashSet<String>();
Scanner in = new Scanner(System.in);
while (!isStop(in)) {
    String word = in.next();
    words.add(word);
}

Is there any other way to stop scanner loop? I can't believe that book's author has made a mistake ?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
RichardK
  • 3,228
  • 5
  • 32
  • 52

5 Answers5

3

The loop stops as soon as this condition is false:

in.hasNext()

I.e., there are no more words.

Inside the loop is a command to read the next word:

in.next()

So words will continue to be read until the Scanner has no more words to read. This loop will terminate at the end of whatever the Scanner is reading.

La-comadreja
  • 5,627
  • 11
  • 36
  • 64
  • 1
    Thanks, but what can I do take make it false ? I didn't find the way – RichardK Oct 21 '14 at 14:24
  • You don't "do" anything. This condition hasNext() is an automatic check of the stream the Scanner scans, which gives "true" if there are still words in the stream and "false" if there aren't. What you can "do" to make it false eventually is keep running the program on the input until the Scanner finishes. Hopefully that explanation is clear to you, let me know if it isn't. – La-comadreja Oct 21 '14 at 15:33
1

Since you are scanning System.in, the loop won't stop as it will keep on adding "words" to your Set but there's no visible error in the program.

Your idea of selecting a keyword to stop the loop once a user input matches that keyword sounds good.

You don't really need a static method using your Scanner as argument for that.

Just add the following after String word = in.next();:

if (word.equalsIgnoreCase("stop")) {
    System.out.printf("Quitting with set: %s%n", words);
    in.close();
    return; // assuming method is void
}
Mena
  • 47,782
  • 11
  • 87
  • 106
  • `in.next()` advances the parser. `in.hasNext()` checks if there is any more input to read. The loop does terminate when there is no more input left to read. – Luminous Oct 21 '14 at 14:23
  • @Luminous the `Scanner` is scanning `System.in` in this example. It will continue to scan as long as the user types text. A good way to control this is to stop based on a keyword. You can of course compare `next` with an empty `String` as well (i.e. a single carriage return). – Mena Oct 21 '14 at 14:25
  • What happens when the user is done typing text? [This code example](http://ideone.com/vcAXXr) proves the loop does terminate. There's no code that signifies for the loop to wait for more text to be entered. – Luminous Oct 21 '14 at 14:35
  • @Luminous The loop terminates once the user types "stop[return]", as designed. I recommend using an actual IDE to test code. – Mena Oct 21 '14 at 14:36
  • (in.equals("stop")) stops scanner already. (!in.equals("stop")) doesn't work here. That's why I've made another static method. – RichardK Oct 21 '14 at 14:48
1

The scanner will continue while there are still words in the input, as others explained. Note that when we're talking about System.in, it usually waits until the user enters more text, and so will not terminate until the user closes the stream (supplies the appropriate end-of-file for the operating system). In Unix/Linux, for the loop to terminate, the user will need to use control-D.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • Thank you. I also tried to close the stream and in throwed exception. I couldn't find the other way stop it, but to make a static method. – RichardK Oct 21 '14 at 14:49
  • The user (who enters the input) is the one who should close the stream by issuing the appropriate character (ctrl-D in unix/Linux/Mac, ctrl-Z in Windows). Note that after that, if there are additional attempts to read from System.in (or any reader based on it) they will not read anything. – RealSkeptic Oct 21 '14 at 14:54
1

The loop won't stop as it will keep on adding "words" to your Set but there's no visible error in the program.

Your idea of selecting a keyword to stop the loop once a user input matches that keyword sounds good.

You don't really need a static method using your Scanner as argument for that.

Just add change your code as follows:

Set<String> words = new HashSet<String>();
Scanner in = new Scanner(System.in);
System.out.print("Type a word...");
while (in.hasNext()) {
    String word = in.next();
    if (word.equalsIgnoreCase("stop")) {
        System.out.printf("Quitting with set: %s%n", words);
        return; // assuming method is void
    }
    else {
        words.add(word);
        System.out.print("Type a word (or \"stop\" to quit)...");
    }
}
Mena
  • 47,782
  • 11
  • 87
  • 106
  • Thanks I tried this first, but didn't work somehow :) – RichardK Oct 21 '14 at 14:42
  • I changed it like this and it's working, thank you: boolean cont = true; while (cont) { String word = in.next(); if (word.equalsIgnoreCase("stop")) { cont = false; } – RichardK Oct 21 '14 at 14:56
  • @RichardK cool! I've edited my answer with more details in case it helps you. – Mena Oct 21 '14 at 15:03
1

IF there is code to be executed after the loop then yes, I'd say the authors made a mistake. Write to them about it! If this is an example of adding items to a Set then the example is fine. It all depends on what the authors' intent of the example was.

hasNext() is a blocking method meaning it will always wait for more input. There are related questions about this. Your way of "fixing this" is what the general consensus has done.

Community
  • 1
  • 1
Luminous
  • 1,771
  • 2
  • 24
  • 43
  • 1
    The Whole code doesn't inlude method to stop the scanner loop. I will inform book author, thank you. – RichardK Oct 21 '14 at 15:44