Topic 8: ArrayLists

In Topic 6 we covered arrays. We saw that an array was a variable which could be used to hold more than one item. However, there is a problem with the use of arrays. We have to give them a fixed capacity (capacity=number of members the array will hold) which cannot change. For example, this program (there is also an Employee class, but this is not shown) will read in employee records from the keyboard, but the array has a fixed initial size of 10 which cannot be changed:

import java.util.Scanner;

public class FixedArraysApp1
{
    public static void main (String[] args)
    {
        Employee[] employees = new Employee[10];
        String name, jobTitle;
        Scanner scanner = new Scanner(System.in);
        
        for(int count=0; count<10; count++)
        {
            System.out.println("Enter employee name:");
            name = scanner.nextLine();
            System.out.println("Enter employee job title:");
            jobTitle = scanner.nextLine();

            employees[count] = new Employee( name, jobTitle );
        }

        for(int count=0; count<10; count++)
        {
            employees[count].display();
        }
        
    }
}
A slight enhancement of this can be made by specifying a variable for the array capacity when we create it, e.g.:
import java.util.Scanner;

public class FixedArraysApp2
{
    public static void main (String[] args)
    {
        Scanner scanner = new Scanner(System.in);
        
        System.out.println("How many employees");
        String numString = scanner.nextLine();
        int numEmployees = Integer.parseInt(numString);
        
        Employee[] employees = new Employee[numEmployees];
        String name, jobTitle;
        
        
        for(int count=0; count<numEmployees; count++)
        {
            System.out.println("Enter employee name:");
            name = scanner.nextLine();
            System.out.println("Enter employee job title:");
            jobTitle = scanner.nextLine();
        
            Employee e = new Employee( name, jobTitle );
            employees[count] = e;    
        }

        for(int count=0; count<numEmployees; count++)
        {
            employees[count].display();
        }
    }
}
In this example, we are reading in the number of employees from the keyboard and creating the array using this value. This is a bit more flexible than the first example, but still has the problem that once we have specified an initial size for the array, we cannot change it. If the user enters 20, for example, the array's capacity will be 20, and we will not be able to add more than 20 employees. But what if the user then realised that there were more than 20?

Introducing the ArrayList

This is where the ArrayList can come in useful. An ArrayList is a built-in Java class which can vary in capacity. We can create an ArrayList and then keep adding objects to it until the JVM's memory runs out. This makes the ArrayList much more flexible than a plain array. Here is an example of code which uses an ArrayList:

// Product class
public class Product
{
    private String name;
    private double price;
    private int quantityInStock;
    
    public Product (String nameIn, double priceIn, int quantityIn)
    {
        name = nameIn;
        price = priceIn;
        quantityInStock = quantityIn;
    }
    
    public void print()
    {
        System.out.println("Name=" + name + " Price=" + price + " Quantity in stock=" + quantityInStock);
    }
}
// Main class
import java.util.ArrayList;

public class ArrayListExample1
{
    public static void main (String[] args)
    {
        ArrayList<Product> products = new ArrayList<Product> ();
        
        Product product1 = new Product("Smartphone", 299.99, 5);
        Product product2 = new Product("Tablet", 199.99, 3);
        Product product3 = new Product("SD Card", 9.99, 100);
        
        products.add(product1);
        products.add(product2);
        products.add(product3);
        
        for(int count=0; count<products.size(); count++)
        {
            Product currentProduct = products.get(count);
            currentProduct.print();
        }
    }
}

A more efficient version of the above code

The code above was written in a way to try and make it as clear as possible what is going on. However, we could write the code more efficiently (less lines of code) as follows:

import java.util.ArrayList;

public class ArrayListExample1
{
    public static void main (String[] args)
    {
        ArrayList<Product> products = new ArrayList<Product> ();
        
        products.add(new Product("Smartphone", 299.99, 5));
        products.add(new Product("Tablet", 199.99, 3));
        products.add(new Product("SD Card", 9.99, 100));
        
        for(int count=0; count<products.size(); count++)
        {
            products.get(count).print();
        }
    }
}
Note how, rather than creating three variables product1, product2 and product3, we create the product objects and add them to the array list in one statement. This is perfectly acceptable as the add() method of the ArrayList is expecting a Product object as a parameter - and we are giving it one.

Note also how we combine two statements into one in the for loop. Rather than storing the current member of the ArrayList in a variable called currentProduct and then calling the print() method on currentProduct, we call the print() method directly on the return value of products.get(count). Since products.get(count) gives us a Product object, this is, again, acceptable.

Exercises