In this tutorial, we will learn a very important topic ArrayList in Java with example and programs in the collection. The interviewer may ask one or two questions from this topic. So, we will try to learn you in a simple and easy way so that you can easily understand it. 

ArrayList in Java

➲ java.util.ArrayList is Resizable-array that can grow or shrink as needed. It is created with an initial size. When this size is exceeded, the collection is automatically grown. When objects are removed, the array can be shrunk.

➲ Elements in ArrayList are placed according to the zero-based index. That is the first element will be placed at 0 index and last element at index (n-1) where n is the size of ArrayList.
➲ It uses a Dynamic array internally for storing the group of elements or data.

Hierarchy diagram of ArrayList in Java

Hierarchy diagram of ArrayList can be shown in the below figure.
Hierarchy diagram of Arraylist in Java.
➲ As shown in the above hierarchy diagram, ArrayList implements the List interface and extends AbstractList(Abstract class) which implements List interface. 
➲ It also implements 3 markers interfaces- Random Access, Cloneable, and Serializable. 
Marker interface is those interface which does not have any methods or any member variables. It is also called an empty interface because of no field or methods.

Random Access Interface

➲ RandomAccess Interface is a marker interface that does not define any method or members. It is introduced in Java 1.4 version for optimizing the list performance. 
➲ RandomAccess interface is present in java.util package.

➲ ArrayList and Vector classes implement a random access interface so that we can access any random element with the same speed. For example, suppose there is a group of one crore objects in the ArrayList. Assume that the first element is x, 10th element is y, and 1st crore element is z. 

Now assume that first element x can be accessed within only 1 sec.  Due to the implementation of random access interface, the 10th element and 1st crore element can also be accessed within the 1 sec. Thus, Any random element we can access with the same or constant speed. Therefore, if our frequent operation is retrieval operation then ArrayList is the best choice.

Serializable Interface

➲ Serializable interface is a marker interface which is used to send the group of objects over the network. It is present in the package.
➲ It helps in sending the data from one class to another class. Usually, we use collections to hold and transfer objects from one place to another place. To provide support for this requirement, every collections class already implements Serializable and Cloneable.

Cloneable Interface

➲ A cloneable interface is present in java.lang package.

➲ It is used to create exactly duplicate objects. When the data or group of objects came from the network, the receiver will create duplicate objects. The process of creating exactly duplicate objects is known as Cloning. It is a very common requirement for collection classes.

Properties of ArrayList in Java

1. Resizable-array: ArrayList is a Resizable array or Growable array that means the size of ArrayList can increase or decrease in size at runtime. Once ArrayList is created, we can add any number of elements.

2. Index-based structure: It is an index based structure in Java.
3. Duplicate elements: Duplicate elements are allowed in the ArrayList.
4. Null elements: Any number of null elements can be added in ArrayList.

5. Insertion order: It maintains the insertion order in Java. That is insertion order is preserved.
6. Heterogeneous objects: Heterogeneous objects are allowed everywhere except TreeSet and TreeMap. Heterogeneous means different elements.

7. Synchronized: It is not synchronized. That means multiple threads can use the same ArrayList simultaneously. 
8. Random Access: ArrayList implements random access because it uses index-based structure. Therefore, we can get, set, insert, and remove elements of the ArrayList from any arbitrary position.

9. Performance: In ArrayList, Manipulation is slow because if any element is removed from ArrayList, a lot of shifting takes place. 
For example:
If ArrayList has 500 elements and if we remove 50th elements then the 51st element will try to acquire that 50th position, and likewise all elements. Thus, it consumes a lot of time-shifting. 

ArrayList Constructors

Creating an array list object is very simple. First, we will declare an array list variable and call the array list constructor to instantiate an array list object and then assign it to the variable. 
There is different ways or methods of constructing an ArrayList object. They are as follows:

1. ArrayList al=new ArrayList();

It creates an empty ArrayList with default initial capacity of 10. i.e. we can store only 10 elements as shown in below daigram.
Arraylist representation in java
Suppose we insert the 11th element into an array at 10th position, what will happen internally?

Once ArrayList is reached its maximum capacity, a new ArrayList is created with new capacity =(current capacity*3/2) + 1 = 10*3/2 + 1= 16 and copies all these existing elements into a new array before adding the new elements and then reassign the reference variable to the new array objects.

The old default array objects of the collection are gone for the garbage collection. Similarly, If we try to insert 17th element, new capacity= 16*3/2 + 1 = 25.

2. ArrayList al=new ArrayList(int initialCapacity);

It creates an empty ArrayList with initial capacity. If you know the initial capacity, you can directly use this object. So, the performance of the system by default will be improved.
For example, suppose our requirement is 500 elements, we will go for this method like this.
     ArrayList list2=new ArrayList(500);

3. ArrayList al=new ArrayList(Collection c);

It creates an array list that is initialized with the elements of collection c. 
For example:
    ArrayList list3=new ArrayList(list1); // list1 is the elements of collection.

Code to create Generic ArrayList

If you are using Java 1.5 or later, we can also specify the type of elements in the array list object. For example:
We can create a generic String array list like this:
 ArrayList<String> al=new ArrayList<String>(); // The advantage of specifying a type is that when we try to add another type of an element, it will give compile-time error. Here, List can be used to store only String types. Storing any other type will give the compilation error. 
Creating a Generic ArrayList object can also be done in separate lines like this:
      ArrayList<String> arlist;
          arlist=new ArrayList();
Note: We cannot use primitive data types as a type. For example, ArrayList<int> is illegal.

How do we manually increase or decrease the current capacity of an ArrayList?

1. ensureCapacity() method: 

This method is used to increase the current capacity of ArrayList. Since the capacity of an array list is automatically increased when we add more elements than current capacity but to increase manually, ensureCapacity() method is used.
For example: 
   ArrayList<String> list=new ArrayList<String>(); // Here list can hold 10 elements.(Default initial capacity).
   list.ensureCapacity(20); // Now it can hold 20 elements.

2. trimTosize() method:

It is used to trim the capacity of arraylist to the current size of arraylist.
For example:

Initialization of ArrayList in Java

There are three methods to initialize ArrayList. They are as follows:
a. Method 1: Using Arrays.asList.
    ArrayList<Type> list=new ArrayList<Type>(Arrays.asList(Object o1, Object o2, .. so on));
For example:
    ArrayList<String> ar=new ArrayList<String>(Arrays.asList("A", "B", "C"));

b. Method 2: Using Normal way
   ArrayList<Type> obj=new ArrayList<Type>();
      obj.add("Obj o1");
      obj.add("Obj o2");
      and so on.

c. Method 3: Using Anonymous Inner class
    ArrayList<Type> arl=new Arraylist<Type>() {{
         add(Object o1);
         add(Object o2);
         add(Object o3);
            . .. .. . . .. 
            . . . . . . . 

 Methods of ArrayList in Java

There are some important methods in the ArrayList which is always used in the programs. They are: 
1. boolean add(Object o): This method is used to add the element at the end of the list. For example,  If you want to add the element at the end of the list, you simply call add() method like this:
    list.add("Shubh"); This will add "Shubh" at the end of the list.

2. boolean addAll(Collection c): This method is used to add a group of elements in a particular collection at the end of the list.
For example, suppose we have a group of elements in the list2 and want to add at the end of the list1, we will call this method like this:

3. boolean addAll(int index, Collection c): This method is used to add a group of elements at a specified position in a list.
For example:
    list1.addAll(2, list2): // add all the elements of list2 at position index 2 in the list1

4. void add(int index, Object o): It is used to add an element at a particular position index in the list.
For example:
    list.add(3, "a"); // add element 'a' at position index 3 in the list.

5. void addAll(int index, Object o): It is used to add a specific element at a particular position in the list. For example, suppose we want to a specific element "Shubh" at a position 2 in the list, we will call add(int index, Object o) method like this:
   list.add(2,"Shubh"); //  This will add "Shubh" at the second position.

Let's see an example program related to all the above points
Program source code 1:.
    package ArrayListTest; import java.util.ArrayList; public class AddExample { public static void main(String[] args) { // Create an object of the non-generic ArrayList. ArrayList al=new ArrayList(); // list1 with default capacity 10. al.add("A"); al.add("B"); al.add(20); al.add("A"); al.add(null); System.out.println(al); // Create an object of another non-generic ArrayList. ArrayList al1=new ArrayList(); // list2 al1.add("a"); al1.add("b"); al1.add("c"); // Call addAll(Collection c) method using reference variable al to add all elements at the end of the list1 al.addAll(al1); System.out.println(al); // Call addAll(int index, Collection c) method using reference variable al1 to add all elements at specified position 2. al1.addAll(2, al); System.out.println(al1); } }
    Output: [A, B, 20, A, null] [A, B, 20, A, null, a, b, c] [a, b, A, B, 20, A, null, a, b, c, c]
In the preceding example program, we have used duplicate elements, heterogeneous elements (i.e String and integer), and a null element. You will also notice that when a specified element is added at a particular position, the right side element is shifted one position right.
After shifting, the object reference variable will reassign new array list as shown in the above picture. Due to shifting, ArrayList is also time-consuming.

In the output, we are getting square bracket notation for this ArrayList. This is because when we try to print an object reference variable, internally it calls toString() method like this:
   System.out.println(al); ------> System.out.println(al.toString());

5. boolean remove(Object o): It removes the first occurrence of the specified element from this list if it is present. 
For example:

6. void remove(int index): Removes the element from the particular position in the list.
For example
    list.remove(2); //  It will remove the element from the position 2.

7. void clear(): It is used to remove all the elements from any list.

8. void set(int index, Object o): It replaces element at a particular position in this list with the specified element. For example, suppose we want to replace the element "A" at a position 2 with an element "a" in this list, we will have to call this method like this:
    list.set(2, "a");

Program source code 2:
Let's create a program where we will remove an element using remove() method from list.
    package ArrayListTest; import java.util.ArrayList; public class RemoveEx { public static void main(String[] args) { // Create the object of generic Array list with String type. This means the compiler will show an error if we try to put any other element than String. ArrayList<String> al=new ArrayList<String>(); // Default capacity is 10. // Now add the elements of String type. al.add("A"); al.add("B"); al.add("C"); al.add("D"); al.add(null); al.add("D"); System.out.println(al); // Call remove method to remove the element D. al.remove("D"); // removes the first occurrence of the specified element D at position 3, not from the position 5. System.out.println(al); al.remove(3); System.out.println(al); // Call set method to replace the element D with a null element at position 3. al.set(3, null); System.out.println(al); } }
    Output: [A, B, C, D, null, D] [A, B, C, null, D] [A, B, C, D] [A, B, C, null]
In this example program, you will observe that when an element is removed or deleted from an array, the deleted element becomes null but the empty slot occupied by the deleted element stays in the array and any subsequent elements at the right side in the array is automatically shifted towards one position left to fill empty slot that was occupied by the deleted element and object reference variable 'al' will be reassigned to the new array list like as shown in the above diagram.

9. Object get(int index): It returns the element at the specified position in this list. 
For example:
      String str=list.get(2);

10. int size(): It returns the number of elements in the list. Size means the number of elements present in the array list.
Capacity means the capability to store elements.
 For example:
      int numberOfElements=list.size();

11. boolean contains(Object o): It returns true if the specified element is present in the list else it returns false.
For example:
Program source code 3:
    package arrayListPrograms; import java.util.ArrayList; public class ArrayListTest { public static void main(String[] args) { ArrayList al=new ArrayList(); al.add("Apple"); al.add("Orange"); al.add("Banana"); al.add("Gauva"); System.out.println(al); // Call get() method using object reference variable 'al' to get the specified element. Since return type of get() method is String. Therefore, we will store it by using a fruitsName variable with data type String. String fruitsName=al.get(2); System.out.println(fruitsName); // Call size() method to get the number of elements present in the list. Since return type of size method is an integer. Therefore, we will store it by using variable numberOfElements with data type integer. int numberOfElements=al.size(); System.out.println(numberOfElements); // Check apple element is present or not. boolean check=al.contains("Apple"); System.out.println(check); } }
    Output: [Apple, Orange, Banana, Gauva] Banana 4 true
12. int indexOf(Object o): It is used to get the index of the first occurrence of the specified element, if the element is not present in the list, it returns the value -1.
For example:
     int pos=list.indexOf("Apple"); 

13. int lastIndexOf(Object o): It is used to get the index of the last occurrence of the specified element in the list. If the element is not present in the list, it returns -1.
For example:
     int lastPos=list.lastIndexOf(20);
Program source code 4:
    package ArrayListTest; import java.util.ArrayList; public class Test { public static void main(String[] args) { ArrayList<Integer> list=new ArrayList<Integer>(); list.add(10); list.add(20); list.add(30); list.add(40); System.out.println(list); int pos=list.indexOf(30); System.out.println(pos); int lastPos=list.lastIndexOf(40); System.out.println(lastPos); } }
    Output: [10, 20, 30, 40] 2 3

When to use ArrayList in Java?

ArrayList can be used when
1. We want to store duplicate elements.
2. We want to store null elements.
3. It is more preferred in Java when getting of the element is more as compared to adding and removing elements. 
4. We are not working in the multi-threading environment in Java because ArrayList is non-synchronized.

Final words
Hope that this tutorial has covered almost all important points related to ArrayList in Java and practical example programs. I hope that you will have understood this topic and enjoyed it.
Thanks for reading!
Next Iterators in Java

⏪ Prev Next ⏩