In this series, we will discuss the Java Collections Framework.
In Java, we have a Collection interface extended by other interfaces such as List, Set, and Queue. We also have a Map interface. The Map does not extend the Collection interface because it stores key-value pairs, and the classes that come under the Collection interface store only values.
Collection vs. Collections
- A Collection is an interface, whereas Collections is a class.
- A Collection interface provides the standard functionality of a data structure to List, Set, and Queue. However, the Collections class provides the utility methods that can be used to search, sort, and synchronize collection elements.
List in Java: ArrayList
ArrayList is an list based on array. Some of the salient features of an ArrayList are:
- Elements are stored in the order of insertion.
- It allows the storage of duplicate elements.
- ArrayList also supports null elements.
An ArrayList stores data in a resizable array. After Java 8, when an ArrayList is created, an array of size zero is created. Only when the first element is inserted does the array size change to ten. This is called lazy initialization, and it saves a lot of memory.
In CS61B, we've discussed resizing an array in lecture 7, and also implemented it in project 1. The strategy we used is doubling the length. In real Java, the strategy is changing length from n
to (n + n/2 + 1)
.
1 | /** Create an ArrayList */ |
Time Complexities for Operations
- Add an element
If an ArrayList is not full, it will take O(1) time.
However, if it is full, it will take extra time to do resizing ... O(N), where N is the number of elements of the ArrayList before adding.
- Remove an element
You can remove an element by giving its index, or giving itself.
- Remove by index:
- O(1) in the best case, ... remove the last element.
- O(n) in the worst case. ... remove the first element, and copy the rest
- Remove by element itself:
- scan the array to find the element, then remove it if it exists.
1 | /** Remove */ |
- Fetch an element
Fetch an element from an ArrayList using index takes O(1) constant time.
1 | /** Fetch */ |
- Insert elements
1 | /** Insert */ |
- Replace all elements in Java 8
A new method, replaceAll(UnaryOperator<E> operator)
, was added in Java 8. This method takes a single UnaryOperator type argument. The UnaryOperator interface is a functional interface that has a single abstract method, apply()
, that returns a result of the same object type as the operand.
1 | import java.util.ArrayList; |
- Update an element
1 |
|
- Check existence
1 | import java.util.ArrayList; |
Iteration
Using Iterator
In CS61B lecture 11, we have discussed enhanced for loop.
1 | import java.util.ArrayList; |
If we try to directly remove an element while iterating an ArrayList using an iterator is created, then ConcurrentModificationException
will also be thrown. We should always use the remove()
method in the iterator to remove an element from the ArrayList.
1 | /** This program will fail because we are trying to delete the element from the list directly. */ |
1 | /** This program is the correct way to delete an element from the list. */ |
If an element is added to the ArrayList after the iterator is created then also ConcurrentModificationException
will be thrown.
1 | import java.util.ArrayList; |
Using ListIterator
The Iterator
provides very limited capabilities as we can iterate only in the forward direction and we can’t update or insert an element to the list while iterating. To overcome these problems, we can use ListIterator
.
1 | import java.util.ArrayList; |
Besides, there are other methods such as remove()
, set(E e)
, add(E e)
etc.