Course – LS – All

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

>> CHECK OUT THE COURSE

1. Overview

When we program in Java, the ability to manipulate data seamlessly is an important skill. We may face scenarios where we need to extract a specific number of elements from a List and store them in an array.

In this tutorial, we’ll explore the steps to retrieve the first n elements from a List and convert them into an array in Java.

2. Introduction to the Problem

As usual, let’s understand the problem through examples. Say we have a list of seven strings:

List<String> INPUT_LIST = Lists.newArrayList("one", "two", "three", "four", "five", "six", "seven");
int n = 5;

Now, we want to take the first n (n=5) elements and convert them into a string array. Of course, the five elements should preserve the order in the original list:

"one", "two", "three", "four", "five"

In this tutorial, we’ll explore different approaches to achieving our goal. For simplicity, we assume the given n won’t be greater than the list’s size. Also, we’ll use unit test assertions to verify whether each method produces the expected result.

Next, let’s dive into the code.

3. Using a for Loop

A straightforward idea to solve the problem is first creating an empty array with the length n, then looping through the first n elements in the list and filling the prepared array in turn.

So next, let’s implement this idea using a for loop:

String[] result = new String[n];
for (int i = 0; i < n; i++) {
    result[i] = INPUT_LIST.get(i);
}
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result);

The code above is pretty straightforward to understand. It does the job.

In our example, the list is an ArrayList. As the name implies, ArrayList is backed by an array. Therefore, ArrayList’s random access complexity is O(1). In other words, calling ArrayList’s get(i) method is performant.

However, not all List implementations offer O(1) random access. For example, LinkedList always navigates from the first node to the desired one. So, its random access cost is O(n)

Since we’re not solving an ArrayList-specific problem, let’s improve our code slightly.

As we need to iterate from the first element to the n-th element, we can use an Iterator to get each element instead of calling the get() method to avoid the random access calls:

String[] result2 = new String[n];
Iterator<String> iterator = INPUT_LIST.iterator();
for (int i = 0; i < n && iterator.hasNext(); i++) {
    result2[i] = iterator.next();
}
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result2);

4. Using the subList() Method

We’ve seen the solution based on a for loop. Another idea to solve the problem is to divide it into two parts:

  • Get the first n elements
  • Convert the extracted elements to an array

The List interface provides the subList() method, which allows us to retrieve continuous elements from a list object. So the first part is easy using INPUT_LIST.subList(0, n) .

We can convert a list to an array in many ways for the second part. Next, let’s see them as examples.

First, let’s pass a prepared array to the List.toArray() method:

String[] result = new String[n];
INPUT_LIST.subList(0, n)
  .toArray(result);
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result);

As we can see, if the array parameter passed to the toArray() method has enough room for the elements in the list, which is the sublist in our case, the toArray() method fills the array with the list elements.

However, if the array argument doesn’t have enough room for the list elements, toArray() allocates a new array carrying the list’s element:

String[] result2 = INPUT_LIST.subList(0, n)
  .toArray(new String[0]);
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result2);

As the code above shows, we didn’t allocate an array with n length. Instead, when we call the toArray() method, we pass “new String[0]” as the parameter. As a result, toArray() creates and returns a new array filled by the list’s elements.

If we work with Java 11 or later version, we can pass a generator function to the toArray() method:

// available only for java 11+
String[] result3 = INPUT_LIST.subList(0, n)
  .toArray(String[]::new);
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result3);

As we can see, we only need to create a new array instance for the generator function, nothing more. Therefore, we used the method reference of String[]’s constructor as the generator function.

5. Using the Stream API

Additionally, we can solve the problem using the Stream API. Stream API is a significant new feature that Java 8 brought us. Therefore, it’s available only for Java 8 or later version:

String[] result = INPUT_LIST.stream()
  .limit(n)
  .toArray(String[]::new);
assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result);

In the example above, we used the limit(n) method to make the Stream only return the first n elements from the source, INPUT_LIST. Then, we called Stream‘s toArray() method to convert the stream object to an array. Similar to Java 11’s List.toArray(), Stream.toArray() accepts a generator function. So, again, we passed the “String[]::new” to the method and got the expected array.

6. Conclusion

In this article, we’ve explored different approaches to extracting the first n elements from a list and converting them to an array through examples.

As always, the complete source code for the examples is available over 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.