Time estimate: 45 min.

8.1. Intro to ArrayLists

../_images/lists.jpg

Figure 1: A couple of lists

In the last unit, we learned about using arrays to hold collections of related data. However arrays are not very flexible. Most notably, the size of an array is set at the time of creation and cannot be changed.

What if you don’t know how big the collection of data will be? What if you want to both add and remove items from a collection? For example, if you wanted to represent a shopping list, you might add to the list throughout the week and remove things from the list while you are shopping. You probably would not know how many items will be on the list at the beginning of the week. Thus arrays are not a very convenient way to represent a shopping list.

For cases like this, Java provides a wide variety of class collectively referred to as “collections” classes. In the AP curriculum we will cover one called ArrayList which is a re-sizable list. It is called ArrayList because it stores the items that have been added to it in an underlying array. But it also takes care of keeping track of how many items have been added to the array and it will create a new bigger array under the covers when needed to hold more items.

You can use ArrayList instead of arrays whenever you don’t know the size of the array you need or you know that you will add and remove items and may need to change the array’s size dynamically during run time. An ArrayList is mutable, meaning it can change during run time by adding and removing objects from it.

Note

An ArrayList is sometimes called just a list on the CSA exam. Prior to 2020 the AP CSA curriculum included interfaces which are somewhat like classes and the interface List was often used to declare a variable that would refer to an ArrayList. Interfaces are no longer on the exam, but if you see List being used in an old exam question just assume it’s an ArrayList.

8.1.1. Packages and imports

To use the ArrayList class we need to learn a little bit about Java packages. A package is a set or library of related classes that can be used in other classes.

The classes we have used until now, such as String and Math, are in the special package java.lang whose classes are always available in any Java program.

The ArrayList class, on the other hand, is defined in a different package, java.util. To use classes from packages like java.util we must either import them or (much more rarely) refer to them by their full name which includes the package as a prefix. The full name of ArrayList is thus java.util.ArrayList. But rather than type that out all the time, in any source file where we want to use ArrayList we will usually import it with an import statement.

Import statements have to come before the class definition in a Java source file and serve to tell Java which class you mean when you use a short name like ArrayList. To import just one class we use a single import of the fully-qualified name of the class like this:

// Import just the ArrayList class from java.util
import java.util.ArrayList;

After such an import statement, anywhere ArrayList is used as a class name in the file it will be taken to mean java.util.ArrayList.

Another option is to import all the classes in a package with a “wildcard” import:

// Import everything in java.util including ArrayList
import java.util.*;

This import statement will also cause, ArrayList to refer java.util.ArrayList. But many other names of classes defined in the java.util package will also be available whether you use them or not. (One that you have probably used by now is Scanner which can be used to read input a user types at the command line.) Using wildcard imports can cause conflicts if you import all the classes from two different packages and they have class names in common but usually that’s not a problem, at least with packages that are part of Java itself.

Note

Don’t worry about adding import statements on the AP CSA exam. Any that you need will be provided for you.

exercise Check your understanding

8.1.2. Declaring and Creating ArrayLists

ArrayLists are also the first example we’ve seen of a generic type. They are generic in the sense that we can make ArrayLists to hold any kind of object, Strings, Turtles, whatever, similar to the way we can make different kind of arrays to hold different kinds of values.

This means that when we declare an ArrayList, we use the syntax ArrayList<Type> to specify the actual type of the ArrayList where Type, called a type parameter, is the type of objects we want to store in the ArrayList. For example a variable naming an ArrayList meant to hold Strings is declared as ArrayList<String> as shown in the code below. Note that when you invoke the constructor you still need the <> after ArrayList but you don’t have to specify the type parameter again—the compiler can infer it. (You can specify it again if you really want.)

// An ArrayList of Strings:
ArrayList<String> shoppingList = new ArrayList<>();

Note

You can declare a variable to just be of type ArrayList, with no type parameter, and then you can put any kind of object at all into it, but it is good practice to always specify the type of objects you intend to store in an ArrayList as it allows the compiler to find errors that would otherwise be missed until run time.

coding exercise Coding Exercise

In the code below we are declaring a variable called nameList that can refer to a ArrayList of strings, but currently doesn’t refer to any ArrayList yet as it’s set to null.

As with other reference types, declaring a ArrayList variable doesn’t actually create a ArrayList object. It only creates a variable that can refer to a ArrayList or null. To actually create a ArrayList we must invoke a constructor such as new ArrayList<>().

You can get the number of items in a ArrayList using the size() method. Notice that a newly constructed ArrayList is empty and thus has a size of 0. Also remember that you can’t call methods on null so trying to call size on the value of list2 at line 10 below causes a NullPointerException.

The following code demonstrates a NullPointerException. Change the list2 declaration so that it creates a new ArrayList to remove the NullPointerException.

You can also create ArrayLists of integer and double values. However, ArrayLists can only hold reference types, not primitive types such as int and double. Thus if we want to represent a list of numbers or booleans we need to use one of the wrapper classes Integer, Double, or Boolean as the type parameter. But because of autoboxing, if you declare an ArrayList<Integer>, ArrayList<Double>, or ArrayList<Boolean> you can mostly treat the elements of the ArrayList as if they were in fact ints, doubles, or booleans.

You can actually put in any kind of objects in an ArrayList, including instances of classes that you write, such as the Student, Person, or Pet classes from Unit 5.

Here’s an example of a Integer ArrayList.

exercise Check your understanding

Although it is not on the AP exam, you can convert an array to a List using the static method asList from the Arrays helper class: Arrays.asList(arrayname). This list will not actually be an ArrayList but you can pass it to the ArrayList constructor that takes a collection as its argument to make a new ArrayList with the contents of the array.

Note also that ArrayList has a toString method that produces a nice string representation of the contents of the list, unlike the toString method on arrays which produces not very helpful gibberish like [Ljava.lang.String;@4361bd48.

Example code creating an ArrayList from an array.

coding exercise Coding Exercise

You can add values to an ArrayList using its add method, described in detail in the next lesson. Try the code below. Note that the type of the ArrayList, String or Integer, also determines the type of parameters and return types for all of its methods, so add and print work for any type of ArrayList. And when the ArrayList is a list of Integers, autoboxing takes care of wrapping the int arguments like 2 and 4 into instances of Integer for us.

Can you add another item to the shopping list?

8.1.3. groupwork Programming Challenge : FRQ Digits

This programming challenge is based on the 2017 Free Response Question part 1a on the 2017 AP CSA exam. In this question, you are asked to write a constructor for a class called Digits. This constructor takes an integer number as its argument and divides it up into its digits and puts the digits into an ArrayList. For example, new Digits(154) creates an ArrayList with the digits [1, 5, 4].

First, let’s discuss how to break up a number into its digits. Try the code below. What happens if you divide an integer by 10? Remember that in integer division the result truncates (cuts off) everything to the right of the decimal point. Which digit can you get by using % 10 which returns the remainder after dividing by 10? Try a different number and guess what it will print and then run to check.

Set number to a different number and guess what number / and % will return. Which operator gives you a digit in number?

We can use a while loop to print out each digit in reverse order starting from the right (4, 5, 1 for the number 154) while dividing it by 10. You can try it in the active code above. Here is the pseudocode:

  • while number is greater than 0

    • print out the last digit using %

    • change the number to cut off the last digit using /

Now, let’s write a constructor for the Digits class that uses this loop and adds each found digit to the ArrayList instead of printing it out. You can use a special method called Collections.reverse(digitsList); to reverse the order of the digits in the ArrayList after the loop to get them in the right order. In the next lesson, we will also learn how to use a different add method that adds in elements at any index instead of the end.

Complete the challenge below to put the digits of a number in an ArrayList.

8.1.4. Summary

  • ArrayLists are re-sizable lists that allow adding and removing items to change their size during run time.

  • The ArrayList class is in the java.util package. You must import java.util.ArrayList or java.util.* to use it.

  • An ArrayList object contains object references and is mutable, meaning it can change (by adding and removing items from it).

  • The ArrayList constructor ArrayList<>() constructs an empty list of size 0.

  • ArrayList is really a generic type ArrayList<E>, where the type parameter E specifies the type of the elements, like String or Integer that will be stored in a specific ArrayList.

  • ArrayList<E> is preferred over ArrayList because it allows the compiler to find errors that would otherwise be found at run time.

  • When ArrayList<E> is specified, the types of the reference parameters and return type when using its methods are type E.

  • ArrayLists cannot hold primitive types like int or double, so you must use the wrapper classes Integer or Double to put numerical values into an ArrayList. However autoboxing usually takes care of that for you.

You have attempted of activities on this page