Course Content
Java Data Structures
Java Data Structures
List and ArrayList
Let's begin our introduction to a data structure called List
. Above is a flowchart showing us the Hierarchy of Collections and Lists. We can see that it's quite a large and complex diagram, but let's break it down step by step. In this section, we'll get acquainted with a type of collection called lists. We'll explore list types such as ArrayList
, LinkedList
, and Stack
.
Note
We won't be discussing
Vector
, as it is an outdated data structure that ArrayList has entirely replaced.
Because all Lists inherit from the List
interface, we can obviously create objects through the parent interface. But more on that later. Let's talk about the first type of list - ArrayList
.
Above, you see the syntax for creating an ArrayList<>
. There is one unfamiliar thing for you in this syntax - it's the generic. We will talk about generics and how to create them later. For now, remember that we are creating an ArrayList
and specifying the data type that will be stored in this list inside diamant brackets. Remember that lists cannot work with primitive data types. For this, we use wrapper classes.
Let's create a list in the code and try adding a few objects to the list using the add()
method.
main
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numberList = new ArrayList<>(); numberList.add(10); numberList.add(15); numberList.add(5); System.out.println(numberList); } }
As you can see, the add()
method is extremely simple. It simply adds the value specified in the parameters to the list. Also, note that we must import List
and ArrayList
from the java.util
library. However, IntelliJ IDEA automatically imports these libraries for you, so don't worry about it.
Let's take a look at an example of creating a list with our custom data type:
main
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { Dog bob = new Dog("Bob", 2); Dog ben = new Dog("Ben", 1); Dog brian = new Dog("Brian", 5); List<Dog> dogList = new ArrayList<>(); dogList.add(bob); dogList.add(ben); dogList.add(brian); System.out.println(dogList); } } class Dog { String name; int age; public Dog(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
As you can see, we created our own class Dog
and created an ArrayList
with this data type. When printed, we obtained a complete list of all objects in the list.
What do we do if we have an array and want to convert it into a list? We can do that using the Arrays class method - asList()
. With this method, we can create a list that will contain the same elements as the original array. This is often useful when we need to use list methods on an array. The syntax is quite simple:
And we can immediately use it when initializing a new list, for example:
main
package com.example; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { Dog bob = new Dog("Bob", 2); Dog ben = new Dog("Ben", 1); Dog brian = new Dog("Brian", 5); Dog[] dogs = {bob, ben, brian}; List<Dog> dogList = new ArrayList<>(Arrays.asList(dogs)); System.out.println(dogList); } } class Dog { String name; int age; public Dog(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Just as we can turn an array into a list, we can turn a list into an array using the toArray()
method.
ArrayList<> Methods
Let's go through the basic methods for working with a list. Up until this point, we could easily replace lists with arrays, but let's look at the main difference - the methods.
The add()
method is an overloaded method and has a second usage:
We can add an element at a specific index.
Note
Lists, like arrays, have zero-based indexing.
When we add an element in the middle of the list, all the elements to the right shift by one position to make room for the new element. For example, when adding an element to the beginning of the list, all the elements shift one position to the right. Let's look at an example:
main
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); for (int i = 0; i < 5; i++) { // filling `numbers` list with 5 values numbers.add(i); } System.out.println("`numbers` before modifying: " + numbers); numbers.add(2, 10); // adding 10 on the second index System.out.println("`numbers` after first modifying: " + numbers); numbers.add(0, 5); System.out.println("`numbers` after second modifying: " + numbers); } }
The process of how the values change can be seen in the illustration:
Obviously, if we can add objects to the list by index, we can also retrieve objects from the list by their index using the get(int index)
method. Let's look at an example:
main
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); for (int i = 0; i < 5; i++) { // filling `numbers` list with 5 values numbers.add(i); } int element = numbers.get(1); System.out.println(element); } }
We can add, we can retrieve, but can we delete?
Certainly, we can! Using the remove(int index)
method.
This method is also overloaded, so there is another way to remove an element from the list. We can use the remove(Object obj)
method and delete the first occurrence of the specified element.
Let's imagine that we have a large list of all the students in our course. But one of them misbehaved and was expelled. We don't know under which index he was recorded, so we must remove him from the list of students. But there's a catch: the code is a bit broken, and his name may have appeared in the list several times. Let's write a program that will remove all mentions of this student from the list:
main
package com.example; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { String[] names = {"Bob", "Alice", "Charlie", "David", "Eva", "Frank", "Grace", "Hank", "Ivy", "Jack", "Katherine", "Leo", "Mia", "Nathan", "Olivia", "Paul", "Quinn", "Rachel", "Sam", "Tom", "Ursula", "Victor", "Wendy", "Xander", "Yvonne", "Zack", "Bob", "Emily", "Bob", "Jake", "Isabel", "Liam", "Nora", "Bob", "Sophia", "Bob", "Daniel", "Gabrielle", "Mike"}; // expelled student: Bob List<String> students = new ArrayList<>(Arrays.asList(names)); System.out.println("Is Bob present in the list? " + students.contains("Bob")); while (students.contains("Bob")) { students.remove("Bob"); } System.out.println("Is Bob still present in the list after the removal operation? " + students.contains("Bob")); } }
You might have correctly noticed that we used another list method - contains(Object obj)
, which checks whether the specified element is present in the list and returns true
or false
. Using this method, we set the condition for the while
loop execution, thus removing all mentions of a student like "Bob" from the list. Wonderful.
By the way, we could significantly simplify solving this problem using the removeAll(Collection<?> c)
method:
main
package com.example; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { String[] names = {"Bob", "Alice", "Charlie", "David", "Eva", "Frank", "Grace", "Hank", "Ivy", "Jack", "Katherine", "Leo", "Mia", "Nathan", "Olivia", "Paul", "Quinn", "Rachel", "Sam", "Tom", "Ursula", "Victor", "Wendy", "Xander", "Yvonne", "Zack", "Bob", "Emily", "Bob", "Jake", "Isabel", "Liam", "Nora", "Bob", "Sophia", "Bob", "Daniel", "Gabrielle", "Mike"}; // expelled student: Bob List<String> students = new ArrayList<>(Arrays.asList(names)); System.out.println("Is Bob present in the list? " + students.contains("Bob")); List<String> expelledStudents = new ArrayList<>(); expelledStudents.add("Bob"); students.removeAll(expelledStudents); System.out.println("Is Bob still present in the list after the removal operation? " + students.contains("Bob")); } }
The removeAll()
method takes a collection as a parameter containing values that it will remove from the collection on which this method was called.
In this way, we created a collection of expelled students and added "Bob" to it. This allows us to easily expand our code by simply adding new troublemakers to the collection of expelled students over time.
Let's move back on to the list methods; now we have the update method in line. Considering that the add()
method simply shifts all values to the right after itself, we need to figure out how to update a value by index. The set(int index, Object value)
method performs this action:
main
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> example = new ArrayList<>(); for (int i = 1; i <= 5; i++) { example.add(i); } System.out.println("List before modification: " + example); example.set(2, 28); System.out.println("List after modification: " + example); } }
Here it's straightforward; we replaced the element at the second index with the number 28.
Other Methods
We could talk about various methods for working with this list for a long time, but it would take a lot of time. Therefore, you can find all the methods you need with complete documentation and explanations of their operation by opening the ArrayList
class in IntelliJ IDEA. To do this, simply import the ArrayList
library, hold down the command key (ctrl for Windows), and click on ArrayList
. Here, you'll see all the fields and methods of this class, allowing you to familiarize yourself with the methods you might have missed.
Thanks for your feedback!