Guide to the Java ArrayList

1. Overview

In this article, we’re going to take a look at ArrayList class from the Java Collections Framework. We’ll discuss its properties, common use cases, as well as its advantages and disadvantages.

ArrayList resides within Java Core Libraries, so you don’t need any additional libraries. In order to use it just add the following import statement:

import java.util.ArrayList;

List represents an ordered sequence of values where some value may occur more than one time.

ArrayList is one of the List implementations built atop an array, which is able to dynamically grow and shrink as you add/remove elements. Elements could be easily accessed by their indexes starting from zero. This implementation has the following properties:

  • Random access takes O(1) time
  • Adding element takes amortized constant time O(1)
  • Inserting/Deleting takes O(n) time
  • Searching takes O(n) time for unsorted array and O(log n) for a sorted one

2. Create an ArrayList

ArrayList has several constructors and we will present them all in this section.

First, notice that ArrayList is a generic class, so you can parameterize it with any type you want and the compiler will ensure that, for example, you will not be able to put Integer values inside a collection of Strings. Also, you don’t need to cast elements when retrieving them from a collection.

Secondly, it is good practice to use generic interface List as a variable type, because it decouples it from a particular implementation.

2.1. Default No-Arg Constructor

List<String> list = new ArrayList<>();
assertTrue(list.isEmpty());

We’re simply creating an empty ArrayList instance.

2.2. Constructor Accepting Initial Capacity

List<String> list = new ArrayList<>(20);

Here you specify the initial length of an underlying array. This may help you avoid unnecessary resizing while adding new items.

2.3. Constructor Accepting Collection

Collection<Integer> number 
  = IntStream.range(0, 10).boxed().collect(toSet());

List<Integer> list = new ArrayList<>(numbers);
assertEquals(10, list.size());
assertTrue(numbers.containsAll(list));

Notice, that element of the Collection instance are used for populating the underlying array.

3. Add Elements to the ArrayList

You may insert an element either at the end or at the specific position:

List<Long> list = new ArrayList<>();

list.add(1L);
list.add(2L);
list.add(1, 3L);

assertThat(Arrays.asList(1L, 3L, 2L), equalTo(list));

You may also insert a collection or several elements at once:

List<Long> list = new ArrayList<>(Arrays.asList(1L, 2L, 3L));
LongStream.range(4, 10).boxed()
  .collect(collectingAndThen(toCollection(ArrayList::new), ys -> list.addAll(0, ys)));
assertThat(Arrays.asList(4L, 5L, 6L, 7L, 8L, 9L, 1L, 2L, 3L), equalTo(list));

4. Iterate Over the ArrayList

There are two types of iterators available: Iterator and ListIterator.

While the former gives you an opportunity to traverse the list in one direction, the latter allows you to traverse it in both directions.

Here we will show you only the ListIterator:

List<Integer> list = new ArrayList<>(
  IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new))
);
ListIterator<Integer> it = list.listIterator(list.size());
List<Integer> result = new ArrayList<>(list.size());
while (it.hasPrevious()) {
    result.add(it.previous());
}

Collections.reverse(list);
assertThat(result, equalTo(list));

You may also search, add or remove elements using iterators.

5. Search the ArrayList

We will demonstrate how searching works using a collection:

List<String> list = LongStream.range(0, 16)
  .boxed()
  .map(Long::toHexString)
  .collect(toCollection(ArrayList::new));
List<String> stringsToSearch = new ArrayList<>(list);
stringsToSearch.addAll(list);

5.1. Searching an Unsorted List

In order to find an element you may use indexOf() or lastIndexOf() methods. They both accept an object and return int value:

assertEquals(10, stringsToSearch.indexOf("a"));
assertEquals(26, stringsToSearch.lastIndexOf("a"));

If you want to find all elements satisfying a predicate, you may filter collection using Java 8 Stream API using Predicate like this:

Set<String> matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));

List<String> result = stringsToSearch
  .stream()
  .filter(matchingStrings::contains)
  .collect(toCollection(ArrayList::new));

assertEquals(6, result.size());

It is also possible to use a for loop or an iterator:

Iterator<String> it = stringsToSearch.iterator();
Set<String> matchingStrings = new HashSet<>(Arrays.asList("a", "c", "9"));

List<String> result = new ArrayList<>();
while (it.hasNext()) {
    String s = it.next();
    if (matchingStrings.contains(s)) {
        result.add(s);
    }
}

5.2. Searching a Sorted List

If you have a sorted array, then you may use a binary search algorithm which works faster than linear search:

List<String> copy = new ArrayList<>(stringsToSearch);
Collections.sort(copy);
int index = Collections.binarySearch(copy, "f");
assertThat(index, not(equalTo(-1)));

Notice that if an element is not found then -1 will be returned.

6. Remove Elements from the ArrayList

In order to remove an element, you should find its index and only then perform the removal via remove() method. An overloaded version of this method, that accepts an object, searches for it and performs removal of the first occurrence of an equal element:

List<Integer> list = new ArrayList<>(
  IntStream.range(0, 10).boxed().collect(toCollection(ArrayList::new))
);
Collections.reverse(list);

list.remove(0);
assertThat(list.get(0), equalTo(8));

list.remove(Integer.valueOf(0));
assertFalse(list.contains(0));

But be careful when working with boxed types such as Integer. In order to remove a particular element, you should first box int value or otherwise, an element will be removed by its index.

You may as well use the aforementioned Stream API for removing several items, but we won’t show it here. For this purpose we will use an iterator:

Set<String> matchingStrings
 = HashSet<>(Arrays.asList("a", "b", "c", "d", "e", "f"));

Iterator<String> it = stringsToSearch.iterator();
while (it.hasNext()) {
    if (matchingStrings.contains(it.next())) {
        it.remove();
    }
}

7. Summary

In this quick article, we had a look at the ArrayList in Java.

We showed how to create an ArrayList instance, how to add, find or remove elements using different approaches.

As usual, you can find all the code samples over on GitHub.

Related posts:

Converting Between Byte Arrays and Hexadecimal Strings in Java
Spring Cloud AWS – S3
Java Program to Check the Connectivity of Graph Using DFS
Java Program to Generate All Subsets of a Given Set in the Gray Code Order
Java Program to Implement Floyd Cycle Algorithm
Spring Cloud AWS – EC2
Java Program to Implement Strassen Algorithm
Lớp lồng nhau trong java (Java inner class)
Java Program to Implement Binary Search Tree
OAuth2 for a Spring REST API – Handle the Refresh Token in AngularJS
CharSequence vs. String in Java
Spring Boot - Introduction
Spring Security Form Login
Upload and Display Excel Files with Spring MVC
Java Program to find the maximum subarray sum using Binary Search approach
Loại bỏ các phần tử trùng trong một ArrayList như thế nào trong Java 8?
Hướng dẫn Java Design Pattern – Abstract Factory
Spring Cloud AWS – RDS
Recommended Package Structure of a Spring Boot Project
Converting String to Stream of chars
Java Program to Perform integer Partition for a Specific Case
Java Program to Check the Connectivity of Graph Using BFS
Sending Emails with Java
Instance Profile Credentials using Spring Cloud
Giới thiệu Design Patterns
Java Program to Implement Sorting of Less than 100 Numbers in O(n) Complexity
Java TreeMap vs HashMap
Quản lý bộ nhớ trong Java với Heap Space vs Stack
Java Program to Find Nearest Neighbor Using Linear Search
Java Program to Implement Bucket Sort
Java Program to Find ith Largest Number from a Given List Using Order-Statistic Algorithm
Spring Security Basic Authentication