Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In Java, it’s common to read input from a Scanner object. In addition, the input is often stored in an array for further processing.

In this tutorial, we’ll explore how to save scanner input in an array in Java.

2. Introduction to the Problem

There can be three scenarios when we store the input from a Scanner as an array:

  • Single-line input – Each token is an array element.
  • Multiline input – Each line is an array element.
  • Multiline input – Each token of each line is an array element.

We’ll discuss these cases in this tutorial. Also, for simplicity, we’ll feed the Scanner object by a string and use unit test assertions to verify if we get the expected result.

3. Single-Line Input: One Array Element per Token

First, let’s say a Scanner object has this input:

String input = "Java Kotlin Ruby Python Go\n";

As we can see, the input line has five tokens. So, the result array should look like this:

String[] expected = new String[] { "Java", "Kotlin", "Ruby", "Python", "Go" };

Java Scanner‘s default delimiter is whitespace. Also, Scanner.next() allows us to read the next token from the input. Therefore, we can call the next() method in a loop to fill an array:

Scanner scanner1 = new Scanner(input);
String[] result1 = new String[5];
int i = 0;
while (i < result1.length) {
    result1[i] = scanner1.next();
    i++;
}
assertArrayEquals(expected, result1);

Sharp eyes may have noticed that this solution only works for the case of five tokens in the line, as we defined the array’s capacity (5). This is because the Java array is fixed-sized. So, we need to set its size when we instantiate it.

Apparently, this approach isn’t so convenient when we don’t know how many elements are in the input.

Alternatively, we can read the entire input line using the Scanner.nextLine() method and split() the line into an array:

Scanner scanner2 = new Scanner(input);
String[] result2 = scanner2.nextLine().split("\\s+");
assertArrayEquals(expected, result2);

4. Multiline Input: One Array Element per Line

Next, let’s build a multiline input:

String input = new StringBuilder().append("Baeldung Java\n")
  .append("Baeldung Kotlin\n")
  .append("Baeldung Linux\n")
  .toString();

Then, we expect each line in the input becomes an element in the result array:

String[] expected = new String[] {"Baeldung Java", "Baeldung Kotlin", "Baeldung Linux"};

We can call Scanner.nextLine() to read an input line and fill an array in a loop:

String[] result = new String[3];
Scanner scanner = new Scanner(input);
int i = 0;
while (i < result.length) {
    result[i] = scanner.nextLine();
    i++;
}
assertArrayEquals(expected, result);

Similarly, we’ve set the size (3) as we declare the array object in the code above.

Since List is with dynamic size, we can use a List to store the lines if we don’t know the number of lines in the input:

List<String> expected = Lists.newArrayList("Baeldung Java", "Baeldung Kotlin", "Baeldung Linux");
List<String> result = new ArrayList<>();
Scanner scanner = new Scanner(input);
while (scanner.hasNextLine()) {
    result.add(scanner.nextLine());
}
assertEquals(expected, result);

Of course, if our final result must be an array, we can easily convert the result List to an array.

5. Multiline Input: One Array Element per Token

Now, let’s look at how to store tokens from a multiline input in an array. Let’s say we have this two-line input:

String input = new StringBuilder().append("Linux Windows MacOS\n")
  .append("Java Kotlin Python Go\n")
  .toString();

And we’d like to have an array containing these elements:

String[] expected = new String[] { "Linux", "Windows", "MacOS", "Java", "Kotlin", "Python", "Go" };

To solve the problem, we can read each input line using Scanner.nextLine() and split() each line into an array. Also, we need to merge this array with the final result array.

Next, let’s see how it works:

String[] result = new String[] {};

Scanner scanner = new Scanner(input);
while (scanner.hasNextLine()) {
    String[] lineInArray = scanner.nextLine().split("\\s+");
    result = ObjectArrays.concat(result, lineInArray, String.class);
}
assertArrayEquals(expected, result);

In the test above, we’ve used Guava‘s ObjectArrays.concat() to concatenate two arrays for simplicity.

However, concatenating arrays create a new array and copies the two arrays into the new one. Therefore, this approach can be slow, especially when we have a large number of input lines.

To get better performance, we can use a List to store the tokens:

List<String> expected = Lists.newArrayList("Linux", "Windows", "MacOS", "Java", "Kotlin", "Python", "Go");

List<String> result = new ArrayList<>();
Scanner scanner = new Scanner(input);
while (scanner.hasNext()) {
    result.add(scanner.next());
}
assertEquals(expected, result);

Again, if required, we can convert the list result into an array.

6. A Word About Array vs. List

As we walked through the approaches to solving our problem, we may have realized that storing the input into a List is more flexible than an array. Apart from the dynamic size attribute, lists have other advantages compared to arrays, for example:

  • Easy to add and remove elements
  • Type-safety
  • Convenient built-in operations, such as indexOf(), contains(), and so on
  • Various implementations, such as ArrayList, LinkedList, and so on

Therefore, when we work on a Java project, we should consider using lists over arrays.

7. Conclusion

In this article, we’ve learned how to store the input from a Scanner into an array.

Further, we’ve discussed three different scenarios and explored each solution through examples.

As usual, all code snippets presented here are available on GitHub.

Course – LS – All

Get started with Spring and Spring Boot, through the Learn Spring course:

>> CHECK OUT THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.