In this chapter, we'll learn about Collections in Java.
A Collection is an object that holds references to other objects. These are data structures and the objects within the collection are known as elements.
Java provides a collections framework which consists of interfaces, classes and methods to store and manipulate aggregate data.
Some collections allow duplicate elements, while others require every element to be unique.
Some collections are ordered, while others are not.
All of the interfaces and classes for the collections framework can be found in the
Let's take a look inside of the Collections Framework.
Collection itself is an interface and is the root of the hierarchy. Java does not provide any direct implementations of the
Collection interface, but there are other interfaces which inherit from
Here are some of the most common ones.
Set is a collection which cannot contain duplicate elements.
An example use case for
Set would be a standard deck of 52 playing cards, where each card would be an element in the collection and each of them are unique.
List is a collection where the elements are ordered.
List can contain duplicate elements.
An example of where
List might be used would be the phone numbers from your call history. They are listed in order and some numbers may appear more than once.
Queue is a collection of ordered elements, which is typically used to hold items that are going to be processed in some way.
An example use case would be the people in the checkout line at a supermarket. People who are new to the queue are added at the end and the processing of the queue is handled from the beginning. This type of processing is well known as first in-first out (FIFO).
Then finally we have
Map, which is not a true collection, meaning it does not inherit from the
Collection interface. However, it contains collection-like operations, which enable them to be used as collections.
Maps are used to hold key/value pairs.
An example for this would be a list of bank transactions where each
Map entry has a unique transaction ID serving as the key and the value would be the actual transaction object.
Let's look at a couple examples of these collections.
Here's an example of a set.
Set is an unordered collection of unique objects. Because
Set is an interface, it cannot be instantiated, but it can be an object's type. This is demonstrated on line 1.
Some implementations of
TreeSet. I won't go into details for these; however, I have placed a link in the resources section should you want to go deeper on this topic.
Notice in our example here, we use the
add method to place items into the set. Note that if I did attempt to add a duplicate to the set, like we're doing with “lemon” on line 6, no error would occur. However, the duplicate elements simply would not be stored.
When we call
fruit.size() on line 8, we're returned with the number 4.
When I print out the set on line 9, the order is not the same order that I added the elements to the set. Since the set is unordered, we have no control over where our elements will be placed.
Please note that while I'm demonstrating this using Strings, collections can hold any type of object.
Here are the methods available for sets.
These are the ones that set inherited from
Collection, no more were added. I won't read these to you, but the link to the set Javadoc is in the Resources section below.
Next, let's look at Lists.
Some implementations of lists are
Vector. There's a link to the Javadoc in the Resources section.
Lists are ordered, so the elements can be accessed by their position in the lists as shown on line 8. Just as with arrays, the index starts at 0.
List can also contain duplicate elements. We added “lemon” on line 3 and line 6 and they both were stored in the array as demonstrated by
fruit.size() returning 5 on line 9, and then also on line 10 we see lemon appear twice.
Also, note on line 10 when we print the list, we see that the elements stayed in the order that we added them.
In addition to the methods inherited from
Collection, here are some additional methods available for lists.
Notice a lot of them have to do with accessing or manipulating the positioning of the elements.
Next, let's look at queues.
Queues hold items to be processed.
The elements are ordered, and the collection can contain duplicates.
The most common implementations of
PriorityQueue, which you can read more about in the Javadocs.
Queues typically follow the first in-first out algorithm — which means elements are processed in the order in which they are entered. For example, on line 11 we call
fruit.remove(). We didn't have to specify which object to remove, it will remove the first one in the queue.
The first element of the
Queue is known as the head. By calling
remove(), we removed “apple” from the queue, which was the head.
The last element of a
Queue is known as the tail.
Sometimes we may want to know what's the next item to be processed before we actually do anything. For that you can use
peek(), which is on line 14. This returns the head of the queue.
In addition to the basic
Queue also provides additional methods for insertion, removal and inspection of elements.
Finally, let's look at maps.
Map interface maps unique keys to values.
You can access an element in a
Map by its key. While the keys are required to be unique, the values are not.
Popular implementations of the map interface are
LinkedHashMap, which you can read more about in the Javadocs.
Let's say that we wanted to add calorie information for each of the fruits. We can use the fruit name as a key and the calories as the value.
Map is not technically a
Collection, meaning it does not inherit from the
Map does not have access to the
add method that we've seen in the other data structures.
Map has a
put method, which is used to add the elements. The
put method takes two arguments — a key and a value. We are using the fruit’s name as the key and the calories as the value.
This example uses String and Integer as the key in value, but you can use any objects here.
Notice that on line 8, when we get the size of this map, it is 4. But we attempted to add 5 values, yet there’s only 4 because the entry on line 6 is not a unique key.
However, when we look at the value that's printed out for key “lemon” on line 11, we see that it did indeed store that entry. That's because, if you call
put passing in a key that already exists, the map will update that entry with the new value that was passed in. So, what we did on line 3 was technically an update.
There is another method called
putIfAbsent(), which you can call to prevent yourself from unintentionally overriding something that's already in the map.
entrySet(), like on line 13, will get you a
Set object which technically then is a
Then line 15 shows how you remove an element by its key.
Here are some of the methods provided by the
In the examples so far, we’ve used the
add() method to add elements to collections.
There’s an easier way to add elements, and that’s by using this
As you see here on line 1, we are adding elements to this list by using
List.of() and passing in all of the elements we want to store within the list.
While this offers a great convenience in setting up this collection, it does come with a cost.
By setting a collection in this way, the collection becomes immutable, meaning it cannot change.
For example, calling the
remove() methods on this collection after using
List.of() will throw an
The same is true for Sets as well as Maps.
In the next section I'll show you how to loop through items in collections.