Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

1. Overview

The Scanner class is a handy tool that can parse primitive types and strings using regular expressions and was introduced into the java.util package in Java 5.

In this short tutorial, we'll talk about its hasNext() and hasNextLine() methods. Even though these two methods may look pretty similar at first, they're actually doing quite different checks.

You can also read more about the versatile Scanner class in the quick guide here.

2. hasNext()

2.1. Basic Usage

The hasNext() method checks if the Scanner has another token in its input. A Scanner breaks its input into tokens using a delimiter pattern, which matches whitespace by default. That is, hasNext() checks the input and returns true if it has another non-whitespace character.

We should also note a few details about the default delimiter:

  • Whitespace includes not only the space character, but also tab space (\t), line feed (\n), and even more characters
  • Continuous whitespace characters are treated as a single delimiter
  • The blank lines at the end of the input are not printed — that is, hasNext() returns false for blank lines

Let's take a look at an example of how hasNext() works with the default delimiter. First, we'll prepare an input string to help us explore Scanner‘s parsing result:

String INPUT = new StringBuilder()
    .append("magic\tproject\n")
    .append("     database: oracle\n")
    .append("dependencies:\n")
    .append("spring:foo:bar\n")
    .append("\n")  // Note that the input ends with a blank line
    .toString();

Next, let's parse the input and print the result:

Scanner scanner = new Scanner(INPUT);
while (scanner.hasNext()) {
    log.info(scanner.next());
}
log.info("--------OUTPUT--END---------")

If we run the above code, we'll see the console output:

[DEMO]magic
[DEMO]project
[DEMO]database:
[DEMO]oracle
[DEMO]dependencies:
[DEMO]spring:foo:bar
[DEMO]--------OUTPUT--END---------

2.2. With Custom Delimiter

So far, we've looked at hasNext() with the default delimiter. The Scanner class provides a useDelimiter(String pattern) method that allows us to change the delimiter. Once the delimiter is changed, the hasNext() method will do the check with the new delimiter instead of the default one.

Let's see another example of how hasNext() and next() work with a custom delimiter. We'll reuse the input from the last example.

After the scanner parses a token matching the string “dependencies:“, we'll change the delimiter to a colon ( : ) so that we can parse and extract each value of the dependencies:

while (scanner.hasNext()) {
    String token = scanner.next();
    if ("dependencies:".equals(token)) {
        scanner.useDelimiter(":");
    }
    log.info(token);
}
log.info("--------OUTPUT--END---------");

Let's see the resulting output:

[DEMO]magic
[DEMO]project
[DEMO]database:
[DEMO]oracle
[DEMO]dependencies:
[DEMO]
spring
[DEMO]foo
[DEMO]bar


[DEMO]--------OUTPUT--END---------

Great! We've successfully extracted the values in “dependencies“, however, there are some unexpected line-break problems. We'll see how to avoid those in the next section.

2.3. With regex as Delimiter

Let's review the output in the last section. First, we noticed that there's a line break (\n) before “spring“. We've changed the delimiter to “:” after the “dependencies:” token was fetched. The line break after the “dependencies:” now becomes the part of the next token. Therefore, hasNext() returned true and the line break was printed out.

For the same reason, the line feed after “hibernate” and the last blank line become the part of the last token, so two blank lines are printed out together with “hibernate“.

If we can make both colon and whitespace as the delimiter, then the “dependencies” values will be correctly parsed and our problem will be solved. To achieve that, let's change the useDelimiter(“:”) call:

scanner.useDelimiter(":|\\s+");

The “:|\\s+” here is a regular expression matching a single “:” or one or more whitespace characters. With this fix, the output turns into:

[DEMO]magic
[DEMO]project
[DEMO]database:
[DEMO]oracle
[DEMO]dependencies:
[DEMO]spring
[DEMO]foo
[DEMO]bar
[DEMO]--------OUTPUT--END---------

3. hasNextLine()

The hasNextLine() method checks to see if there's another line in the input of the Scanner object, no matter if the line is blank or not.

Let's take the same input again. This time, we'll add line numbers in front of each line in the input using hasNextLine() and nextLine() methods:

int i = 0;
while (scanner.hasNextLine()) {
    log.info(String.format("%d|%s", ++i, scanner.nextLine()));
}
log.info("--------OUTPUT--END---------");

Now, let's take a look at our output:

[DEMO]1|magic	project
[DEMO]2|     database: oracle
[DEMO]3|dependencies:
[DEMO]4|spring:foo:bar
[DEMO]5|
[DEMO]--------OUTPUT--END---------

As we expected, the line numbers are printed, and the last blank line is there, too.

4. Conclusion

In this article, we've learned that Scanner‘s hasNextLine() method checks if there is another line in the input, no matter if the line is blank or not, while hasNext() uses a delimiter to check for another token.

As always, the complete source code for the examples is available over on GitHub.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

Generic footer banner
Comments are closed on this article!