Java 11 Developer Certification - List and ArrayList

April 02, 2021

What we are covering in this lesson

  1. Introduction
  2. List interface
  3. ArrayList
  4. Generics
  5. ArrayList Methods

Introduction

We had seen some details on List interface in the previous sections. Here, we will look at those in detail, and also look at ArrayList. The last section where we saw the differences between interface and classes will also be helpful here, so in case you have missed it, go through it once!

List interface

So lets begin by talking about java.util.List. The declaration of java.util.List is an interface that extends the Collection interface.

public Interface List<E> extends Collection<E> {

The javadocs for List interface is here.

So below would be the brief from javadocs -

  • java.util.List is an ordered collection.
  • The user of this interface has precise control over where in the list, each element is inserted.
  • The user can access elements by their integer index, and search for elements in the list.
  • Unlike sets, lists typically allow duplicate elements, and they typically also allow multiple null elements, if they allow null elements at all.

ArrayList

Lets look at ArrayList now. So this is a class that extends the AbstractList, and implements the List among other interfaces. The declaration of java.util.ArrayList is as below

public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable

The javadocs for ArrayList is here

  • java.util.ArrayList is a resizable-array implementation of the List Interface.
  • It implements all optional list operations, and permits all elements, including null.
  • In addition to implementing the List interface, this class provides methods to manipulate the size of the array, that is used internally to store the list.
  • So this list is roughly equivalent to Vector, except that it’s unsynchronized.
  • Importantly, note that ArrayLists do not support primitive data types.
  • You will have to use the primitive data wrapper classes.

Generics

Generics are most commonly used in List and ArrayList. So why use generics? We did touch base on this topic briefly in previous sections but generics enable types, classes and interfaces, to be parameters when defining classes, interfaces and methods. Similar to parameters used in method declarations, these type parameters provide a way for you to re-use the same code with different types of inputs. Before Java 5, an ArrayList was a collection of any object you wanted to put in there. If you were always putting a String element in the ArrayList, you’d have no way to enforcing, or of enforcing this rule, and you always had to cast to a String, when you retrieved an element from the ArrayList.

Java 5 introduced a generic ArrayList which allows the person using an ArrayList in their code to provide a type for the ArrayList. You can create your own types that are parameterized. The ArrayList class was changed to Java 5 to be such a type, allowing the consumer of the type to decide what elements are permissible, when adding elements to the collection, prompting the compiler to do type-checking.

Some of the benefits gained by declaring your type are -

  • Stronger type checks at compile time
  • Elimination of casts
  • Enabling programmers to implement generic algorithms.

Lets look at a small sample code which will give us a brief idea on how to use List and ArrayList.

We need to import java.util.ArrayList and java.util.List for this. And we have declared some local variables of type List and ArrayList. Most of the declarations are using generics, specifying a type in the diamond operator, to declare a type for a parameterized type.

As we know we cannot instantiate an interface, and so we cannot create a List instance. We can create an instance of a class that implements the List interface and assign it to the the List type, as we have done in the below code.

We have demonstrated 3 ways to instantiate an ArrayList, two of which are typed. We can always leave out the type on the right hand side and keep the right diamond operator empty. You cannot create List object but you can set objects that implement List to a List variable, as done in the last two lines of code.

package maxCode.online.list;

import java.util.ArrayList;
import java.util.List;

public class ListDeclaration {
	public static void main(String[] args) {
		// List variable declarations
		List l;
		List<Integer> intList;
		List<ArrayList> arrayList;

		// ArrayList variable declarations
		ArrayList a;
		ArrayList<String> stringArray;
		ArrayList<Integer> integerArray;

		// Instantiation of ArrayList objects
		// Initialize a non-typed ArrayList using no args constructor
		a = new ArrayList();

		// Initialize the String-typed ArrayList using the int argument
		// which sets the initial capacity of the ArrayList
		stringArray = new ArrayList<String>(10);

		// Initialize the Integer-typed ArrayList using the Collections
		// parameter which passes values to the ArrayList
		integerArray = new ArrayList<Integer>(List.of(10, 20, 30));

		// You can leave the type out of the right hand set of <>
		ArrayList<String> abc = new ArrayList<>();

		// This generates a warning but compiles
		ArrayList<String> def = new ArrayList();

		// You cannot create List object but you can set objects that
		// implement List to a List variable
		l = a;
		intList = integerArray;
	}
}

ArrayList Methods

Below table shows some of the methods used in ArrayList.

Type of Functionality ArrayList Method
Comparision equals
isEmpty
Searches contains
containsAll
indexOf
lastIndexOf
Data Manipulation add
addAll
clear
forEach
get
hashCode
remove
removeAll
removeIf
replaceAll
retainAll
set
size
sort
Data Transformation copyOf (Java 10)
iterator
listIterator
of (Java 9)
splitIterator (Java 8)
subList
toArray

So continuing with the previous code, we will use these methods now. Firstly, we add some data to the ArrayList without specifying any index, which means the data will get updated to the end of the list. Then in the next loop, we are adding data specifying index. We have also used addAll variations and some output data to print the results.

The next set of methods used are remove, removeIf, replaceAll, retainAll and removeAll, and printing using forEach and lambda expression.

package maxCode.online.list;

import java.util.ArrayList;
import java.util.List;

public class ListDeclaration {
	public static void main(String[] args) {
		// List variable declarations
		List l;
		List<Integer> intList;
		List<ArrayList> arrayList;

		// ArrayList variable declarations
		ArrayList a;
		ArrayList<String> stringArray;
		ArrayList<Integer> integerArray;

		// Instantiation of ArrayList objects
		// Initialize a non-typed ArrayList using no args constructor
		a = new ArrayList();

		// Initialize the String-typed ArrayList using the int argument
		// which sets the initial capacity of the ArrayList
		stringArray = new ArrayList<String>(10);

		// Initialize the Integer-typed ArrayList using the Collections
		// parameter which passes values to the ArrayList
		integerArray = new ArrayList<Integer>(List.of(10, 20, 30));

		// You can leave the type out of the right hand set of <>
		ArrayList<String> abc = new ArrayList<>();

		// This generates a warning but compiles
		ArrayList<String> def = new ArrayList();

		// You cannot create List object but you can set objects that
		// implement List to a List variable
		l = a;
		intList = integerArray;

		// add some data
		for (int i = 0; i < 5; i++) {
			// adds data at end of list...
			stringArray.add("String_" + (i + 1));
			integerArray.add(i + 1);
		}
		System.out.println(stringArray);
		System.out.println(integerArray);

		// add some data at certain index
		for (int i = 0; i < 5; i++) {
			// adds data at end of list...
			stringArray.add(1, "String_" + (i + 1));
			integerArray.add(1, i + 1);
		}
		System.out.println(stringArray);
		System.out.println(integerArray);

		// addAll adds a collection of data, this call appends data to
		// end of list
		integerArray.addAll(List.of(15, 25, 30));
		System.out.println(integerArray);

		// addAll adds a collection of data, this call inserts all
		// elements of the list starting at the index, moving existing
		// elements to a higher index location
		integerArray.addAll(1, List.of(150, 250, 300));
		System.out.println(integerArray);

		// Remove a single element, and only the first match, using
		// remove method
		stringArray.remove("String_5");
		System.out.println("stringArray after removing one element, String_5 " + stringArray.toString());

		// Remove a matching element
		stringArray.removeIf(s -> s.contains("_2"));
		System.out.println("stringArray after removing any elements that contain '_2' " + stringArray.toString());

		// Replaces values in the array using a lambda expression
		stringArray.replaceAll((s) -> s.replace("String_", "Test_"));
		System.out.println("stringArray after replaceAll  " + stringArray.toString());

		// Put them back the way they were...
		stringArray.replaceAll((s) -> s.replace("Test_", "String_"));

		// Remove a set of elements using removeAll method
		// Note that the list you pass removeAll may contain elements
		// that are not in stringArray. It will remove matched elements
		stringArray.removeAll(List.of("String_1", "String_3", "String_10"));
		System.out.println("stringArray after removing several elements " + stringArray.toString());

		// Keep only a defined set of elements using ArrayList.retainAll
		stringArray.retainAll(List.of("String_4"));
		System.out.println("stringArray after retaining only String_4 " + stringArray.toString());

		// Print String objects in the list using forEach
		stringArray.forEach((s) -> System.out.println(s));
	}
}

Output

[String_1, String_2, String_3, String_4, String_5]
[10, 20, 30, 1, 2, 3, 4, 5]
[String_1, String_5, String_4, String_3, String_2, String_1, String_2, String_3, String_4, String_5]
[10, 5, 4, 3, 2, 1, 20, 30, 1, 2, 3, 4, 5]
[10, 5, 4, 3, 2, 1, 20, 30, 1, 2, 3, 4, 5, 15, 25, 30]
[10, 150, 250, 300, 5, 4, 3, 2, 1, 20, 30, 1, 2, 3, 4, 5, 15, 25, 30]
stringArray after removing one element, String_5 [String_1, String_4, String_3, String_2, String_1, String_2, String_3, String_4, String_5]
stringArray after removing any elements that contain '_2' [String_1, String_4, String_3, String_1, String_3, String_4, String_5]
stringArray after replaceAll  [Test_1, Test_4, Test_3, Test_1, Test_3, Test_4, Test_5]
stringArray after removing several elements [String_4, String_4, String_5]
stringArray after retaining only String_4 [String_4, String_4]
String_4
String_4

Thats all for this section. We will be discussion specific methods of List and ArrayList in the next section.