Is ArrayList a class?

Java ArrayList is perhaps the simplest and one of the most used data structure implementation classes of the Java API Library. It is a part of the Java Collection Framework under the java.util package. On one hand, it behaves like a normal array, providing all the benefits of it and, on the other, it is a generic re-sizable collection implementation of the List interface. Java ArrayList is especially used for managing a large number of objects. This article attempts to provide some information of this utility class with a brief overview of its structure.

Java ArrayList Class Hierarchy

In short, Java ArrayList is a subclass of AbstractList and implements the List interface, and List is an extension of the Collection interface. As a result, we can declare an ArrayList object as any of the ways that follow:

  • Collection<String> collection=new ArrayList<>();
  • List<String> list=new ArrayList<>();
  • ArrayList<String> alist=new ArrayList<>();

Is ArrayList a class?

Figure 1: An ArrayList chart

Refer to the Java API Documentation for more details on the classification.

Java ArrayList Overview

While dealing with data structures in any programming language, we resort to low-level manipulation of data. Creating each element of the data structure dynamically and modifying them by directly manipulating references to it can be erroneous and also daunting at times. Direct manipulation may be necessary on occasion, yet when productivity is concerned, support from the API library comes in quite handy. Java Collection Framework contains many such prepackaged data structures, interfaces, and algorithms. Java ArrayList is one of them and can be used like the low-level arrays with some special connotation.

Java ArrayList uses an array as the internal programming construct to store elements. An array is nothing but a sequential collection same type of elements, accessed by their index values. Naturally, Java ArrayList also behaves in a similar manner. Here, the behavior is defined by the ready-made methods of the ArrayList class. Common operations are add/remove elements in various ways, determine if the list is empty, obtain the size of the list indicated by number of elements present currently, and so forth.

Java ArrayList Constructors

Java ArrayList class contains three constructors, such as:

  • ArrayList(): Constructs an empty list with an initial storage capacity of ten elements.
  • ArrayList(Collection<? Extends E> c): Constructs a list containing elements in a pre-specified collection.
  • ArrayList(int initialCapacity): Constructs an empty list, but we can override the default initial capacity.

Java ArrayList Methods

There are various methods. A few of the commonly used are as follows:

  • boolean add(E obj): Inserts an element at the end of the list.
  • void add(int index, E obj): Inserts an element at the specified index. The elements at that location and subsequent locations are shifted to the right.
  • void clear(): Makes the list completely empty by removing all elements.
  • E remove(int index): Removes an element at the specified index and shifts any subsequent elements to the left.
  • E get(int index): Returns an element at the index position.
  • int indexOf(Object obj): Returns the index of the first occurrence of the element in the list, or returns -1 to indicate that the list does not contain the specified element.
  • boolean contains(Object obj): Returns true if list contains the specified element; otherwise, returns false.
  • boolean isEmpty(): Returns true is there is no element in the list; otherwise, returns false.
  • int size(): Returns the count of elements in the list.

A Quick Example

package org.mano.example; import java.util.ArrayList; import java.util.Random; public class ArrayListDemo1 { public static void main(String[] args) { ArrayList<String> planets = new ArrayList<>(); planets.add("Mercury"); planets.add("Earth"); planets.add("Jupiter"); planets.add("Saturn"); System.out.println(planets); int index = planets.indexOf("Earth"); planets.remove(index); planets.add(1, "Venus"); System.out.println("Size = " + planets.size()); for (index = 0; index < planets.size(); index++) { System.out.println(planets.get(index)); } } }

How to Use the Java ArrayList add() Method

Here is another example showing how to specifically use the Java ArrayList add() method to add elements to an ArrayList object:

import java.util.ArrayList; public class ArrayListDemo2 { public static void main(String[] args) { ArrayList<String> planets = new ArrayList<>(); planets.add("Mercury"); planets.add("Earth"); planets.add("Jupiter"); planets.add("Saturn"); System.out.println(planets); // Adding another element planets.add("Uranus"); System.out.println(planets); } }

When you run the above code, you will see two sets of output. The first shows the elements of the first iteration of <i>planets</i>. Then, we add Uranus as an array element and print out <i>planets</i> again to show that it was, indeed, added.

Generic ArrayList in Java

Java ArrayList is built to support generic types. That is the reason that the class refers to having elements of type E, such as ArrayList<E>. The E is replaced by the type of element such as String, Employee, and so on. There is a subtle difference between a normal array and Java ArrayList: Here we do not create an ArrayList of objects, rather we create an ArrayList object that stores a particular object type. For example, if we want to create an ArrayList of String object type, we may write:

ArrayList<String> strList=new ArrayList<>();

Similarly, for Employee object, we may write:

ArrayList<Employee> empList=new ArrayList<>();

We also may create an ArrayList without specifying a type, such as:

ArrayList <?> unknownList=new ArrayList<>();

This, however, is not always a good practice because we should let the compiler know the type of data element prior to adding it to the list. The ? denotes a wild card. Let us illustrate a case to get a clear idea about the uses of the generic ArrayList, including wildcards.

Suppose we want to implement a list of numbers and a generic sumTotal() method to get a total sum of the number of elements in the collection. By definition, generic classes can be used only with class or interface types. As a result, the numbers should be auto-boxed as objects of a wrapper class, such as an int value would be auto-boxed as Integer or a double value would be auto-boxed as a Double wrapper class. Our sumTotal() function should be able to calculate the total of the numbers in the ArrayList regardless of type variation. Therefore, well declare the ArrayList as ArrayList<Number>. The type argument Number is a super class of both wrapper classes Integer and Double. As a result, the reference variable can hold the reference of both the types. The following code should clarify the point further.

package org.mano.example; import java.util.ArrayList; public class Main { public static void main(String[] args) { Number[] nos = { 10, 20.683, 89, 0.74876 }; ArrayList<Number> nosList = new ArrayList<>(); for (Number no : nos) nosList.add(no); System.out.println(nosList); System.out.println("Sum = " + sumTotal(nosList)); } public static double sumTotal(ArrayList<Number> list) { double sum = 0; for (Number number : list) sum += number.doubleValue(); return sum; } }

So far, so good. The sumTotal() method takes a parameter as ArrayList<Number>; now, what if we want to send an ArrayList<Integer> or say ArrayList<Double> as an argument to the sumTotal() method call? We might expect that the method would work under this circumstance as well. After all, Number is a super class of Integer or Double, right? Unfortunately, it will not work! And, it would issue an error message at compile time. Try this modified code; it will not work.

public class Main { public static void main(String[] args) { Integer[] nos = { 10, 20, 89, 22 }; ArrayList<Integer> nosList = new ArrayList<>(); for (Integer no : nos) nosList.add(no); // ...same as above } public static double sumTotal(ArrayList<Number> list) { // ...same as above } }

The compiler does not consider the parameterized type ArrayList<Number> to be a super type of ArrayList<Integer>, because if ArrayList<Number> is considered a super type, we might add a Double object to an ArrayList<Number>. After all, Double is also a number as well. But, the point is we cannot add a Double object to an ArrayList<Integer> Because Double is not an Integer. This creates a erroneous super-subtype relationship.

Under these circumstances, can we create a sumTotal() method that is flexible enough to work with any subclass of Number? The answer is, we can, but by using wild card type arguments.

Lets modify the preceding example to suit our needs.

package org.mano.example; import java.util.ArrayList; public class Main { public static void main(String[] args) { Integer[] nos = { 10, 20, 89, 22 }; ArrayList<Integer> nosList = new ArrayList<>(); for (Integer no : nos) nosList.add(no); // ...same as above } public static double sumTotal(ArrayList<? extends Number> list) { // ...same as above } }

Conclusion

This article tried to put up some specific points in using the Java ArrayList class. In simple terms, ArrayList is an implementation of the concept of dynamic arrays. Normal arrays are of a static length; they cannot grow or shrink. That means we must specify their capacity prior to using them. Java ArrayList, in essence, is a variable-length array of object references that can dynamically increase or decrease its capacity. It is created with an initial size but, if this size is exceeds, the collection is automatically enlarged. Conversely, when objects are removed, the array is also shrunk.