In Java, an ArrayList is a type of dynamic array that is part of the Java Collections Framework. It is a resizable array that automatically increases its size as more elements are inserted into it.
ArrayLists, originating from the java.util package, are widely utilized due to their convenience and adaptability. Unlike traditional arrays in Java, ArrayLists do not require a predefined size upon instantiation, making them more versatile. This characteristic resembles the behavior of Vectors in C++.
In Java, the ArrayList is capable of containing duplicate elements and it abides by the List interface, allowing access to all List interface functionalities. Internally, the ArrayList ensures the preservation of the order of insertion.
The class inherits functionality from the AbstractList class and also fulfills the requirements of the List interface.
The important points about the Java ArrayList class are:
- Maintains Insertion Order: Java ArrayList guarantees the order in which elements are fed into it. When going through the ArrayList with the iterating process, elements are accessed in the same sequence they were added.
- Non-Synchronized: Unlike some other Java collection classes (for instance, Vector), ArrayList is not synchronized. This fact implies that ArrayList is not thread-safe; therefore, concurrent modification issues might arise if multiple threads access ArrayList concurrently.
- Supports Random Access: ArrayList allows the implementation of fast random access operations using the elements' index positions. This is because an array structure is used for internal implementation, which ensures constant-time access to elements via index.
- Slower Manipulation compared to LinkedList: Manipulation operations, such as insertion and deletion, can be slower in ArrayList than in LinkedList. Thus, ArrayList has to perform the shifting of the elements when items are inserted or removed from anywhere except the end of the list. However, it is effortless to add or delete an element in a LinkedList, and no shifting will be needed.
- Requires Wrapper Classes for Primitive Types: ArrayList does not have a direct support for primitive data types such as
int,float, andchar. Instead, it requires the wrapper classes likeInteger,Float,Character, etc., to hold for these primitive types. For example: - Dynamic Resizing: ArrayList expands or contracts when adding or removing elements to meet the required new size. Due to adaptive resizing, online collections can be managed without physical resizing.
- Capacity: ArrayList has an initial capacity, which is the number of elements it can keep without reallocation. If the number of elements cannot fit into this capacity, the List automatically enlarges the size to accommodate the rest of the elements. Copying all the elements to the new, larger array may be involved.
- Iterable: ArrayList implements the
Iterableinterface. Therefore, we can easily iterate the elements using enhanced for loops or iterators. - Dynamic Initialization: Java ArrayList is initialized without specifying its size. Unlike traditional arrays, where you must declare a fixed size, ArrayList dynamically adjusts its size based on the number of elements added or removed. This dynamic sizing eliminates the need to preallocate memory or worry about exceeding array bounds, providing more flexibility in managing collections.
ArrayList<Integer> integerList = new ArrayList<>();
integerList.add(10); // Here, 10 is automatically boxed into an Integer object
Hierarchy of ArrayList Class
The illustration displayed above demonstrates that the Java ArrayList class is a subclass of the AbstractList class, which in turn implements the List interface. The List interface is an extension of the Collection and Iterable interfaces in a hierarchical manner.
ArrayList Class Declaration
Let's examine the declaration of the java.util.ArrayList class.
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable
The ArrayList<E> class is presented as a generic class that utilizes a type parameter E to define the type of elements saved within the ArrayList. This type parameter, E, allows the ArrayList to accommodate objects of any reference type.
The inheritance relationship denoted by "extends AbstractList<E>" signifies that the ArrayList class is derived from the AbstractList class. AbstractList serves as the foundation for the List interface, offering a comprehensive implementation of nearly all its methods.
The declaration "implements List<E>" signifies that the ArrayList class incorporates the functionalities defined in the List interface. This interface outlines the methods that can be performed on lists and is an extension of the Collection interface.
The ArrayList class implements the RandomAccess marker interface to signify its capability for swift (constant time) random access to elements. This interface serves as a signal for classes that offer efficient random access functionality.
The declaration "implements Cloneable" indicates that the ArrayList class incorporates the Cloneable marker interface. This interface indicates that ArrayList objects can be duplicated by utilizing the clone method.
The implementation of Serializable indicates that the ArrayList class incorporates the Serializable marker interface. By implementing this interface, instances of the ArrayList class can be serialized (transformed into a byte stream) for purposes such as storage or transmission.
Constructors of the ArrayList Class
| Constructor | Description |
|---|---|
| ArrayList() | It is used to build an empty array list. |
| ArrayList(Collection<? extends E> c) | It is used to build an array list that is initialized with the elements of the collection c. |
| ArrayList(int capacity) | It is used to build an array list that has the specified initial capacity. |
Methods of the ArrayList Class
| Method | Description |
|---|---|
| voidadd(int index, E element) | It is used to insert the specified element at the specified position in a list. |
| booleanadd(E e) | It is used to append the specified element at the end of a list. |
| booleanaddAll(Collection<? extends E> c) | It is used to append all of the elements in the specified collection to the end of this list, in the order that they are returned by the specified collection's iterator. |
| booleanaddAll(int index, Collection<? extends E> c) | It is used to append all the elements in the specified collection, starting at the specified position of the list. |
| voidclear() | It is used to remove all of the elements from this list. |
| void ensureCapacity(int requiredCapacity) | It is used to enhance the capacity of an ArrayList instance. |
| E get(int index) | It is used to fetch the element from the particular position of the list. |
| boolean isEmpty() | It returns true if the list is empty, otherwise false. |
| Iterator() | Returns an iterator over the elements in the ArrayList in proper sequence.Allows sequential access to the elements in the ArrayList. |
| listIterator() | Returns a list iterator over the elements in the ArrayList in proper sequence.Allows bidirectional access to the elements in the ArrayList, including adding, removing, and modifying elements during iteration. |
| int lastIndexOf(Object o) | It is used to return the index in this list of the last occurrence of the specified element, or -1 if the list does not contain this element. |
| Object[] toArray() | It is used to return an array containing all of the elements in this list in the correct order. |
| <T> T[] toArray(T[] a) | It is used to return an array containing all of the elements in this list in the correct order. |
| Object clone() | It is used to return a shallow copy of an ArrayList. |
| boolean contains(Object o) | It returns true if the list contains the specified element. |
| int indexOf(Object o) | It is used to return the index in this list of the first occurrence of the specified element, or -1 if the List does not contain this element. |
| E remove(int index) | It is used to remove the element present at the specified position in the list. |
| booleanremove(Object o) | It is used to remove the first occurrence of the specified element. |
| booleanremoveAll(Collection<?> c) | It is used to remove all the elements from the list. |
| boolean removeIf(Predicate<? super E> filter) | It is used to remove all the elements from the list that satisfies the given predicate. |
| protected voidremoveRange(int fromIndex, int toIndex) | It is used to remove all the elements lies within the given range. |
| void replaceAll(UnaryOperator<E> operator) | It is used to replace all the elements from the list with the specified element. |
| voidretainAll(Collection<?> c) | It is used to retain all the elements in the list that are present in the specified collection. |
| E set(int index, E element) | It is used to replace the specified element in the list, present at the specified position. |
| void sort(Comparator<? super E> c) | It is used to sort the elements of the list on the basis of the specified comparator. |
| Spliterator<E> spliterator() | It is used to create a spliterator over the elements in a list. |
| List<E> subList(int fromIndex, int toIndex) | It is used to fetch all the elements that lies within the given range. |
| int size() | It is used to return the number of elements present in the list. |
| void trimToSize() | It is used to trim the capacity of this ArrayList instance to be the list's current size. |
Java Non-generic Vs. Generic Collection
Prior to JDK 1.5, the Java Collections Framework did not support generics, leading to a lack of type safety and necessitating manual type casting during element retrieval from collections.
ArrayList list=new ArrayList();//creating old non-generic arraylist
Within this specialized ArrayList, elements of various types can be incorporated without the compiler ensuring type safety. It allows for the addition of different data types like String and Integer consecutively without undergoing compile-time verification.
Since Java 5 (JDK 1.5) brought in generics, the Collections Framework was updated to support this feature. Generics enable developers to define the type of objects a collection can store during compilation, ensuring type safety and removing the necessity for manual type conversion. Below is a sample demonstrating the creation of a generic ArrayList to illustrate this concept. Let's explore this new approach to constructing Java collections.
ArrayList<String> list=new ArrayList<String>();//creating new generic arraylist
Within this general ArrayList, the type parameter indicates that only elements of type String are permitted in the ArrayList. When attempting to insert an element of a different type, the compiler will detect this during compilation, guaranteeing type safety. For instance, trying to include an Integer in this ArrayList would lead to a compile-time error.
Java ArrayList Example
Example
import java.util.*;
public class Main{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Printing the arraylist object
System.out.println(list);
}
}
Output:
[Mango, Apple, Banana, Grapes]
Iterating ArrayList using Iterator
Traversing an ArrayList by utilizing an Iterator in Java is a frequently used procedure that enables sequential traversal of the elements within the list. Iterators offer a secure and effective means of retrieving elements from a collection, particularly when there is a need to delete elements while traversing. Below is a demonstration of how to iterate through ArrayList elements by employing the Iterator interface.
Example
import java.util.*;
public class Main{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Traversing list through Iterator
Iterator itr=list.iterator();//getting the Iterator
while(itr.hasNext()){//check if iterator has the elements
System.out.println(itr.next());//printing the element and move to next
}
}
}
Output:
Mango
Apple
Banana
Grapes
Iterating ArrayList using For-each loop
Traversing an ArrayList with a for-each loop, also referred to as an enhanced for loop, offers a clear and succinct method to sequentially access items in the list. This technique streamlines the code, proving beneficial when there is no need for index usage or intricate operations during iteration. Below is an illustration demonstrating how to iterate through ArrayList elements utilizing the for-each loop.
Example
import java.util.*;
public class Main{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Mango");//Adding object in arraylist
list.add("Apple");
list.add("Banana");
list.add("Grapes");
//Traversing list through for-each loop
for(String fruit:list)
System.out.println(fruit);
}
}
Output:
Mango
Apple
Banana
Grapes
Get and Set ArrayList
To access and update an ArrayList, you can utilize the get and set methods.
Using get method:
- The get method is used to retrieve the element at a certain index in the ArrayList.
- It takes an integer argument which specifies the element index to be brought back.
- The indexing begins with 0, which represents the initial element, and ends with size - 1 for the last element in the ArrayList.
Using set method:
- The set method is used to replace the element at a specific index in the ArrayList with a new element.
- It takes two parameters: the index of the element to replace and the new element to be placed at that index.
- The previous element at the specified index will be overwritten by the new element.
Example
import java.util.*;
public class Main{
public static void main(String args[]){
ArrayList<String> al=new ArrayList<String>();
al.add("Mango");
al.add("Apple");
al.add("Banana");
al.add("Grapes");
//accessing the element
System.out.println("Returning element: "+al.get(1));//it will return the 2nd element, because index starts from 0
//changing the element
al.set(1,"Dates");
//Traversing list
for(String fruit:al)
System.out.println(fruit);
}
}
Output:
Returning element: Apple
Mango
Dates
Banana
Grapes
How to Sort ArrayList?
Within the java.util package, there exists a utility class called Collections that includes a static method known as sort. By utilizing the Collections.sort method, it becomes straightforward to arrange the elements of an ArrayList in a specific order.
Example
import java.util.*;
class Main{
public static void main(String args[]){
//Creating a list of fruits
List<String> list1=new ArrayList<String>();
list1.add("Mango");
list1.add("Apple");
list1.add("Banana");
list1.add("Grapes");
//Sorting the list
Collections.sort(list1);
//Traversing list through the for-each loop
for(String fruit:list1)
System.out.println(fruit);
System.out.println("Sorting numbers...");
//Creating a list of numbers
List<Integer> list2=new ArrayList<Integer>();
list2.add(21);
list2.add(11);
list2.add(51);
list2.add(1);
//Sorting the list
Collections.sort(list2);
//Traversing list through the for-each loop
for(Integer number:list2)
System.out.println(number);
}
}
Output:
Apple
Banana
Grapes
Mango
Sorting numbers...
1
11
21
51
Ways to iterate the elements of the collection in Java
There are various ways to traverse the collection elements:
- By Iterator interface.
- By for-each loop.
- By ListIterator interface.
- By for loop.
- By forEach method.
- By forEachRemaining method.
Iterating Collection through remaining ways
An illustration is provided below to demonstrate alternative methods for iterating through the elements of an ArrayList.
Example
import java.util.*;
class Main{
public static void main(String args[]){
ArrayList<String> list=new ArrayList<String>();//Creating arraylist
list.add("Ravi");//Adding object in arraylist
list.add("Vijay");
list.add("Ravi");
list.add("Ajay");
System.out.println("Traversing list through List Iterator:");
//Here, element iterates in reverse order
ListIterator<String> list1=list.listIterator(list.size());
while(list1.hasPrevious())
{
String str=list1.previous();
System.out.println(str);
}
System.out.println("Traversing list through for loop:");
for(int i=0;i<list.size();i++)
{
System.out.println(list.get(i));
}
System.out.println("Traversing list through forEach() method:");
//The forEach() method is a new feature, introduced in Java 8.
list.forEach(a->{ //Here, we are using lambda expression
System.out.println(a);
});
System.out.println("Traversing list through forEachRemaining() method:");
Iterator<String> itr=list.iterator();
itr.forEachRemaining(a-> //Here, we are using lambda expression
{
System.out.println(a);
});
}
}
Output:
Traversing list through List Iterator:
Ajay
Ravi
Vijay
Ravi
Traversing list through for loop:
Ravi
Vijay
Ravi
Ajay
Traversing list through forEach() method:
Ravi
Vijay
Ravi
Ajay
Traversing list through forEachRemaining() method:
Ravi
Vijay
Ravi
Ajay
User-defined class objects in Java ArrayList
ArrayLists have the ability to contain instances of custom classes, enabling developers to efficiently handle collections of personalized data types. This feature empowers developers to design collections that align with the unique needs of their applications.
In the case of utilizing user-defined class objects within ArrayLists, every item contained in the ArrayList signifies a specific occurrence of the user-defined class. To illustrate, let's imagine a situation where a Student class embodies individuals containing properties like name, age, and roll number. An ArrayList can be established to retain instances of the Student class:
Consider an instance where we are storing objects of the Student class in an ArrayList.
Example
class Student{
int rollno;
String name;
int age;
Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}
}
import java.util.*;
class ArrayList5{
public static void main(String args[]){
//Creating user-defined class objects
Student s1=new Student(101,"Sonoo",23);
Student s2=new Student(102,"Ravi",21);
Student s3=new Student(103,"Hanumat",25);
//creating arraylist
ArrayList<Student> al=new ArrayList<Student>();
al.add(s1);//adding Student class object
al.add(s2);
al.add(s3);
//Getting Iterator
Iterator itr=al.iterator();
//traversing elements of ArrayList object
while(itr.hasNext()){
Student st=(Student)itr.next();
System.out.println(st.rollno+" "+st.name+" "+st.age);
}
}
}
Output:
101 Sonoo 23
102 Ravi 21
103 Hanumat 25
Java ArrayList Serialization and Deserialization Example
In Java, serialization and deserialization are techniques employed to transform objects into byte sequences for the purpose of storage or communication, and to subsequently recreate the original objects from those byte sequences. This functionality enables objects to be archived in files, transmitted across networks, or persisted in databases.
Let's examine a case where we serialize an ArrayList object and then proceed to deserialize it.
Example
import java.util.*;
class ArrayList6 {
public static void main(String[] args) {
// Create an ArrayList and add elements to it
ArrayList<String> al = new ArrayList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ajay");
try {
// Serialization
FileOutputStream fos = new FileOutputStream("file");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(al); // Write the ArrayList object to the file
fos.close();
oos.close();
// Deserialization
FileInputStream fis = new FileInputStream("file");
ObjectInputStream ois = new ObjectInputStream(fis);
// Read the ArrayList object from the file and cast it to ArrayList<String>
ArrayList list = (ArrayList) ois.readObject();
System.out.println(list); // Print the deserialized ArrayList
ois.close();
fis.close();
} catch (Exception e) {
System.out.println(e);
}
}
}
Output:
[Ravi, Vijay, Ajay]
Java ArrayList example to add elements
Here, we see different ways to add an element.
Example
import java.util.*;
class ArrayList7{
public static void main(String args[]){
ArrayList<String> al=new ArrayList<String>();
System.out.println("Initial list of elements: "+al);
//Adding elements to the end of the list
al.add("Ravi");
al.add("Vijay");
al.add("Ajay");
System.out.println("After invoking add(E e) method: "+al);
//Adding an element at the specific position
al.add(1, "Gaurav");
System.out.println("After invoking add(int index, E element) method: "+al);
ArrayList<String> al2=new ArrayList<String>();
al2.add("Sonoo");
al2.add("Hanumat");
//Adding second list elements to the first list
al.addAll(al2);
System.out.println("After invoking addAll(Collection<? extends E> c) method: "+al);
ArrayList<String> al3=new ArrayList<String>();
al3.add("John");
al3.add("Rahul");
//Adding second list elements to the first list at specific position
al.addAll(1, al3);
System.out.println("After invoking addAll(int index, Collection<? extends E> c) method: "+al);
}
}
Output:
Initial list of elements: []
After invoking add(E e) method: [Ravi, Vijay, Ajay]
After invoking add(int index, E element) method: [Ravi, Gaurav, Vijay, Ajay]
After invoking addAll(Collection<? extends E> c) method:
[Ravi, Gaurav, Vijay, Ajay, Sonoo, Hanumat]
After invoking addAll(int index, Collection<? extends E> c) method:
[Ravi, John, Rahul, Gaurav, Vijay, Ajay, Sonoo, Hanumat]
Java ArrayList example to remove elements
Here, we see different ways to remove an element.
Example
import java.util.*;
class ArrayList8 {
public static void main(String [] args)
{
ArrayList<String> al=new ArrayList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ajay");
al.add("Anuj");
al.add("Gaurav");
System.out.println("An initial list of elements: "+al);
//Removing specific element from arraylist
al.remove("Vijay");
System.out.println("After invoking remove(object) method: "+al);
//Removing element on the basis of specific position
al.remove(0);
System.out.println("After invoking remove(index) method: "+al);
//Creating another arraylist
ArrayList<String> al2=new ArrayList<String>();
al2.add("Ravi");
al2.add("Hanumat");
//Adding new elements to arraylist
al.addAll(al2);
System.out.println("Updated list : "+al);
//Removing all the new elements from arraylist
al.removeAll(al2);
System.out.println("After invoking removeAll() method: "+al);
//Removing elements on the basis of specified condition
al.removeIf(str -> str.contains("Ajay")); //Here, we are using Lambda expression
System.out.println("After invoking removeIf() method: "+al);
//Removing all the elements available in the list
al.clear();
System.out.println("After invoking clear() method: "+al);
}
}
Output:
An initial list of elements: [Ravi, Vijay, Ajay, Anuj, Gaurav]
After invoking remove(object) method: [Ravi, Ajay, Anuj, Gaurav]
After invoking remove(index) method: [Ajay, Anuj, Gaurav]
Updated list : [Ajay, Anuj, Gaurav, Ravi, Hanumat]
After invoking removeAll() method: [Ajay, Anuj, Gaurav]
After invoking removeIf() method: [Anuj, Gaurav]
After invoking clear() method: []
Java ArrayList example of retainAll method
The retainAll function in Java ArrayList is utilized to keep only the elements in the ArrayList that exist in another collection, usually another ArrayList. Essentially, it eliminates all elements from the existing ArrayList that are not part of the specified collection.
Example
import java.util.*;
class Main {
public static void main(String args[]) {
// Create the first ArrayList (al) and add elements to it
ArrayList<String> al = new ArrayList<String>();
al.add("Ravi");
al.add("Vijay");
al.add("Ajay");
// Create the second ArrayList (al2) and add elements to it
ArrayList<String> al2 = new ArrayList<String>();
al2.add("Ravi");
al2.add("Hanumat");
// Retain only the elements that are present in both al and al2
al.retainAll(al2);
// Print the elements of al after retaining the elements of al2
System.out.println("Iterating the elements after retaining the elements of al2:");
Iterator itr = al.iterator();
while (itr.hasNext()) {
System.out.println(itr.next());
}
}
}
Output:
iterating the elements after retaining the elements of al2
Ravi
Java ArrayList example of isEmpty method
The isEmpty function in Java ArrayList is utilized to verify whether the ArrayList is empty. It returns true if the ArrayList does not have any elements, and false if it contains elements.
Example
import java.util.*;
class Main {
public static void main(String[] args) {
// Create an ArrayList
ArrayList<String> al = new ArrayList<String>();
// Check if the ArrayList is empty
System.out.println("Is ArrayList Empty: " + al.isEmpty());
// Add elements to the ArrayList
al.add("Ravi");
al.add("Vijay");
al.add("Ajay");
// Display a message after insertion
System.out.println("After Insertion");
// Check if the ArrayList is empty after insertion
System.out.println("Is ArrayList Empty: " + al.isEmpty());
}
}
Output:
Is ArrayList Empty: true
After Insertion
Is ArrayList Empty: false
Java ArrayList Example: Book
Consider an instance with an ArrayList demonstrating the addition of books to the collection and the subsequent printing of all the listed books.
Example
import java.util.*;
class Book {
int id;
String name,author,publisher;
int quantity;
public Book(int id, String name, String author, String publisher, int quantity) {
this.id = id;
this.name = name;
this.author = author;
this.publisher = publisher;
this.quantity = quantity;
}
}
public class Main {
public static void main(String[] args) {
//Creating list of Books
List<Book> list=new ArrayList<Book>();
//Creating Books
Book b1=new Book(101,"Let us C","Yashwant Kanetkar","BPB",8);
Book b2=new Book(102,"Data Communications and Networking","Forouzan","Mc Graw Hill",4);
Book b3=new Book(103,"Operating System","Galvin","Wiley",6);
//Adding Books to list
list.add(b1);
list.add(b2);
list.add(b3);
//Traversing list
for(Book b:list){
System.out.println(b.id+" "+b.name+" "+b.author+" "+b.publisher+" "+b.quantity);
}
}
}
Output:
101 Let us C Yashwant Kanetkar BPB 8
102 Data Communications and Networking Forouzan Mc Graw Hill 4
103 Operating System Galvin Wiley 6
Size and Capacity of an ArrayList
The concepts of size and capacity in an array list can be perplexing for newcomers. An ArrayList is capable of accommodating a variable number of elements by allowing elements to be added or removed, thereby providing flexibility in managing collections. The size of an ArrayList indicates the quantity of elements it can hold, which can be determined by invoking the size method. This size is automatically updated as elements are added to or removed from the list.
The capacity of an ArrayList refers to the maximum number of elements it can hold before needing to be resized. At the beginning, the capacity of an ArrayList is determined by the constructor that was used to create it, or by the default capacity if no constructor is specified. As the number of elements in the ArrayList exceeds its current capacity, the ArrayList dynamically reallocates and expands its capacity to accommodate more elements, ensuring efficient storage and performance. You can determine the size of the ArrayList by using the capacity method.
In this section, we will explore this concept further through the use of several illustrative examples. Let's examine the code snippet provided below.
Example
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
// Create an ArrayList of Integer type
ArrayList<Integer> al = new ArrayList<Integer>();
// Print the size of the ArrayList using the size() method
System.out.println("The size of the array is: " + al.size());
}
}
Output:
The size of the array is: 0
Explanation: The output remains consistent since no modifications were made to the array list. Let's now examine the subsequent program.
Example
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
// Create an ArrayList of Integer type with an initial capacity of 10
ArrayList<Integer> al = new ArrayList<Integer>(10);
// Print the size of the ArrayList using the size() method
System.out.println("The size of the array is: " + al.size());
}
}
Output:
The size of the array is: 0
Upon observation, it is evident that the size remains at 0 due to the fact that the value 10 signifies the capacity rather than the size. The size actually indicates the overall count of elements within the array. Since no elements have been added, the array list size in both implementations is zero.
Consider having a container named ArrayList with a unique attribute called capacity, specifying the maximum number of elements it can accommodate. For instance, if this container has a capacity of 10.
Begin by placing various objects such as toys into a container. After each item is inserted, verify whether the quantity of items in the container (referred to as its size) matches the maximum capacity. If the size equals the capacity, this indicates that the container is at full capacity, necessitating a larger container to accommodate additional items.
When the box accommodates 10 toys, it reaches its maximum capacity. Any attempt to add an 11th toy reveals that the box is full, necessitating the acquisition of a larger container. In this scenario, a new box with a greater capacity is required since the current one can only store 10 toys.
Now, remember, there are two scenarios:
Initially, you begin with a standard container capable of accommodating up to 10 toys without a defined capacity, as it is the default setting.
In the second case, you clearly specify your requirement by stating, "I require a container that has the ability to accommodate 10 toys." Thus, you will receive a box that has the precise capacity to store 10 toys from the beginning.
However, the procedure remains consistent in both scenarios: continuously adding toys, and when the container reaches its capacity, upgrading to a larger one.
It's important to note that the mechanism for increasing capacity in an ArrayList is not standardized. The specifics of how capacity is increased can differ between different versions of the GDK. To understand how capacity is expanded, it is necessary to examine the implementation of the capacity increase code in the GDK. Unlike the ArrayList class, there isn't a built-in method that directly provides the capacity of an ArrayList. To gain a better insight, you can utilize the capacity method available in the Vector class. The concepts of size and capacity function in a similar manner in both the ArrayList and Vector classes.
Advantages of ArrayList:
Resizable Feature: The ArrayList automatically adjusts its size when elements are added or removed, eliminating the need for manual resizing. This automatic resizing capability enables the ArrayList to accommodate different numbers of elements without requiring manual intervention.
Random Access: The ArrayList provides efficient constant-time access to elements by their index, allowing for quick random access operations. This feature makes ArrayList particularly suitable for scenarios where elements need to be accessed randomly based on their order.
Efficient Traversal: The ArrayList facilitates swift navigation through its elements by utilizing enhanced loops or iterators. This feature proves beneficial as it permits smooth handling of each element in the list in a consecutive manner. Whether opting for a loop or an iterator, you have the ability to effortlessly retrieve and modify every element stored in the ArrayList without employing intricate indexing or traversal algorithms. This streamlined methodology improves code clarity and eases tasks, rendering ArrayList a flexible and user-friendly data structure suitable for a multitude of programming assignments.
Flexibility: ArrayList has the capability to store objects of diverse types, including custom user-defined classes. This flexibility empowers developers to tailor solutions to meet specific requirements of clients by accommodating a variety of data types and structures.
Versatility: The ArrayList offers a variety of methods that allow for the modification, insertion, or positioning of elements within it, enhancing the flexibility in handling data. These methods enable functionalities such as adding, removing, accessing, editing, and more, simplifying the management of data operations.
Introduction to Generics: Java 5 introduced support for generics, enhancing the type safety of ArrayList by allowing the specification of the type of elements it contains. This feature improves the type checking process during compilation, ensuring type safety and reducing the occurrence of runtime errors.
Incorporating Java Collections Framework: The Java Collections Framework incorporates ArrayList, a component that establishes a consistent structure for managing object collections. This integration module ensures harmonious interaction with various sorting algorithms and modules present in the framework.
Disadvantages of ArrayList:
The Overhead of Dynamic Resizing: The capability of ArrayList to dynamically resize itself, which is advantageous for handling additions and removals of elements, can result in a decrease in performance. When the internal array of the ArrayList expands or contracts dynamically, frequent resizing processes, especially in scenarios involving large ArrayLists, can lead to noticeable performance overhead. Each resizing action necessitates the allocation of fresh memory, the transfer of existing elements, and the deallocation of the previous array, thereby consuming computational power and time. Excessive resizing can adversely affect the efficiency of a program, causing delays in execution. Therefore, although the adaptability of ArrayList is a positive trait, developers need to judiciously handle resizing tasks to minimize performance drawbacks and ensure optimal efficiency in applications that manage large lists or frequently modified ArrayLists.
Memory Overallocation: The ArrayList reserves memory in chunks and might reserve extra memory to accommodate potential growth. This can lead to memory wastage, particularly with a sizable ArrayList capacity, even if it holds only a few elements.
Insertion and deletion operations in ArrayList can be inefficient, particularly when performed in the middle or at the start of the list. This inefficiency arises from the need to shift elements within the array list when new elements are added or existing ones are removed.
Inappropriate for Primitive Types: The ArrayList is designed to contain objects and cannot directly hold primitive data types. To store primitive types, wrapper classes like Integer, Double, etc., must be utilized, leading to increased memory consumption and additional boxing/unboxing operations.
Lack of Thread Safety: The ArrayList lacks synchronization and is inherently not thread-safe. When multiple threads concurrently modify an ArrayList, it can lead to unpredictable or corrupted data. To address this issue, external synchronization blocks should be implemented or consider utilizing Vector or CopyOnWriteArrayList as options that are thread-safe.
Reduced Efficiency with Extensive Collections: In cases of significantly large collections, ArrayList may exhibit lower efficiency compared to alternative data structures such as LinkedList and HashSet when performing insertion, deletion, or search tasks. Different data structures may be more suitable for specific scenarios.
Java ArrayList MCQ
- Which of the following interfaces does the Java ArrayList class directly implement?
- Queue
- List
Explanation: The ArrayList class directly implements the List interface. This interface allows for ordered collections and provides methods to manipulate the size and elements of the list. The Set, Queue, and Map interfaces are not directly implemented by ArrayList.
- When an element is removed from an ArrayList, which of the following best describes the impact on the remaining elements?
- All elements are rehashed
- No impact on remaining elements
- Elements after the removed element are shifted left
- ArrayList becomes immutable
In an ArrayList, when an element is deleted, the following elements move to the left to occupy the space left by the deleted element. This process can lead to an O(n) time complexity for the deletion operation, where n represents the count of elements after the deleted one.
- What is the default starting capacity of an ArrayList in the Java programming language?
Explanation: The default initial capacity of an ArrayList when it is created without specifying the capacity is 10. This capacity can increase dynamically as elements are added to the list.
- Which method is used to ensure that an ArrayList instance has at least a specified number of elements?
- trimToSize(int capacity)
- ensureCapacity(int minCapacity)
- increaseCapacity(int capacity)
- setCapacity(int capacity)
Explanation: The ensureCapacity(int minCapacity) method is used to increase the capacity of the ArrayList instance to ensure it can hold at least the number of elements specified by minCapacity. This helps to minimize the number of resizing operations when a large number of elements are expected to be added.
- How does Java ArrayList handle the scenario when its capacity needs to be increased?
- It throws an OutOfMemoryError
- It uses a linked list to accommodate the new elements
- It creates a new array with increased capacity and copies elements over
- It appends elements to a secondary array
In the event that an ArrayList requires additional capacity, it generates a fresh array with an increased capacity (usually 1.5 times the present capacity or greater) and then transfers the current elements to this new array. This resizing process enables the ArrayList to effectively manage dynamic expansion.