Java Collection Interface
Since Java 1.2, we have Java Collections API to represent and manipulate collections in Java in a standard way. There are two "root" interfaces: java.util.Collection
and java.util.Map
. In this article, we will run through the first interface: Collection
.
There is no direct implementation of Collection
interface, but there are classes that implemented through Collection sub-interfaces like List
, Queue
, and Set
. For example:
ArrayList
implementsList
PriorityQueue
implementsQueue
HashSet
implementsSet
Check below diagram for the classes and the "Collection" interfaces they are implemented.
Collection <interface> | List <interface> | ArrayList | |||
---|---|---|---|---|---|
Vector | Stack | ||||
LinkedList | |||||
Queue <interface> | Deque <interface> | ||||
PriorityQueue | |||||
Set <interface> | HashSet | ||||
LinkedHashSet | |||||
SortedSet <interface> | NavigableSet <interface> | TreeSet |
For your notes, the Collection classes are extended from AbstractCollection
class that not in our table above. Here the structure:
AbstractCollection
implementsCollection
AbstractList
implementsList
extendsAbstractCollection
AbstractQueue
implementsQueue
extendsAbstractCollection
AbstractSet
implementsSet
extendsAbstractCollection
ArrayList
,Vector
, andAbstractSequentialList
extendsAbstractList
LinkedList
implementsDeque
and extendsAbstractSequentialList
PriorityQueue
extendsAbstractQueue
TreeSet
implemetsNavigableSet
extendsAbstractSet
To understand fully the structure, you need to understand about Inheritance in Java.
As mentioned above, you cannot create a Collection
instance directly, but an instance of one of the sub-types of Collection
. Here some samples to create Collection
based on different sub-types:
Collection colAL = new ArrayList(); System.out.println(colAL.getClass().getName()); Collection colV = new Vector(); System.out.println(colV.getClass().getName()); Collection colS = new Stack(); System.out.println(colS.getClass().getName()); Collection colLL = new LinkedList(); System.out.println(colLL.getClass().getName()); Collection colPQ = new PriorityQueue(); System.out.println(colPQ.getClass().getName()); Collection colHS = new HashSet(); System.out.println(colHS.getClass().getName()); Collection colLHS = new LinkedHashSet(); System.out.println(colLHS.getClass().getName()); Collection colTS = new TreeSet(); System.out.println(colTS.getClass().getName());
Result:
java.util.ArrayList java.util.Vector java.util.Stack java.util.LinkedList java.util.PriorityQueue java.util.HashSet java.util.LinkedHashSet java.util.TreeSet
For your reference, here the information we can "extract" from a Collection
with sub-type LinkedList
:
Collection ll = new LinkedList(); System.out.println("Class : " + ll.getClass().getName()); Class[] tis = ll.getClass().getInterfaces(); for (Class ti : tis) { System.out.println("Interface : " + ti.getTypeName()); } System.out.println("is Collection: " + (ll instanceof Collection));
Result:
Class : java.util.LinkedList Interface : java.util.List Interface : java.util.Deque Interface : java.lang.Cloneable Interface : java.io.Serializable is Collection: true
Add/Remove Element(s) from a Collection
Following methods can be used to add or remove objects from Collection
:
- boolean add(E e): add one element to this collection.
- boolean addAll(Collection<? extends E> c): add a collection of objects to this collection.
- boolean remove(Object o): remove an element from a collection, if the element is exists.
- boolean removeAll(Collection<?> c): remove elements based on one collection from this collection.
- boolean retainAll(Collection<?> c): keeps elements based on one collection, and removes all other elements in this collection.
The first example is to add element(s) to a Collection
using add(...)
method:
private void addToCollection(Collection collection) { collection.add("one"); collection.add("two"); collection.add("three"); collection.add("one"); collection.add("two"); collection.add("three"); System.out.println(collection.getClass().getName() + " : " + collection); } ... CollectionInterfaceAddRemove app = new CollectionInterfaceAddRemove(); Collection colAL = new ArrayList(); app.addToCollection(colAL); Collection colV = new Vector(); app.addToCollection(colV); Collection colS = new Stack(); app.addToCollection(colS); Collection colLL = new LinkedList(); app.addToCollection(colLL); Collection colPQ = new PriorityQueue(); app.addToCollection(colPQ); Collection colHS = new HashSet(); app.addToCollection(colHS); Collection colLHS = new LinkedHashSet(); app.addToCollection(colLHS); Collection colTS = new TreeSet(); app.addToCollection(colTS);
Result:
java.util.ArrayList : [one, two, three, one, two, three] java.util.Vector : [one, two, three, one, two, three] java.util.Stack : [one, two, three, one, two, three] java.util.LinkedList : [one, two, three, one, two, three] java.util.PriorityQueue : [one, one, three, two, two, three] java.util.HashSet : [one, two, three] java.util.LinkedHashSet : [one, two, three] java.util.TreeSet : [one, three, two]
The app here (and the next samples) will refer to CollectionInterfaceAddRemove
class.
The elements in PriorityQueue
and TreeSet
above are ordered by their natural ordering, since no "custom" Comparator
is used.
HashSet
, LinkedHashSet
, and TreeSet
implements Set
interface which not allowing duplicate elements.
Continue from above example, here the sample to remove an element from a Collection
, using remove(...)
method:
private void removeFromCollection(Collection collection) { collection.remove("two"); System.out.println(collection.getClass().getName() + " : " + collection); } ... app.removeFromCollection(colAL); app.removeFromCollection(colV); app.removeFromCollection(colS); app.removeFromCollection(colLL); app.removeFromCollection(colPQ); app.removeFromCollection(colHS); app.removeFromCollection(colLHS); app.removeFromCollection(colTS);
With result:
java.util.ArrayList : [one, three, one, two, three] java.util.Vector : [one, three, one, two, three] java.util.Stack : [one, three, one, two, three] java.util.LinkedList : [one, three, one, two, three] java.util.PriorityQueue : [one, one, three, three, two] java.util.HashSet : [one, three] java.util.LinkedHashSet : [one, three] java.util.TreeSet : [one, three]
Although not captured in my example, remove()
method return a boolean value. If the element was present, it returns true, else return false.
Still continue from previous example, here the sample for add elements based on a Collection
to a Collection
, using addAll(...)
method:
private void addAllToCollection(Collection collection) { Collection list = new ArrayList(); list.add("uno"); list.add("due"); list.add("tre"); collection.addAll(list); System.out.println(collection.getClass().getName() + " : " + collection); } ... app.addAllToCollection(colAL); app.addAllToCollection(colV); app.addAllToCollection(colS); app.addAllToCollection(colLL); app.addAllToCollection(colPQ); app.addAllToCollection(colHS); app.addAllToCollection(colLHS); app.addAllToCollection(colTS);
The result are:
java.util.ArrayList : [one, three, one, two, three, uno, due, tre] java.util.Vector : [one, three, one, two, three, uno, due, tre] java.util.Stack : [one, three, one, two, three, uno, due, tre] java.util.LinkedList : [one, three, one, two, three, uno, due, tre] java.util.PriorityQueue : [due, one, one, three, two, uno, three, tre] java.util.HashSet : [due, tre, one, uno, three] java.util.LinkedHashSet : [one, three, uno, due, tre] java.util.TreeSet : [due, one, three, tre, uno]
From the example above, we know that we can add elements from one Collection
to another Collection
although it have different sub-type. Variable list which sub-type is an ArrayList
, can be added to Stack
, PriorityQueue
, HashSet
, etc. The result is depends on the Collection sub-type, some allowing duplicates, where others not.
And next, we are using removeAll(..)
to remove elements from a Collection
based on another Collection
.
private void removeAllFromCollection(Collection collection) { Collection set = new HashSet(); set.add("one"); set.add("two"); set.add("three"); collection.removeAll(set); System.out.println(collection.getClass().getName() + " : " + collection); } ... app.removeAllFromCollection(colAL); app.removeAllFromCollection(colV); app.removeAllFromCollection(colS); app.removeAllFromCollection(colLL); app.removeAllFromCollection(colPQ); app.removeAllFromCollection(colHS); app.removeAllFromCollection(colLHS); app.removeAllFromCollection(colTS);
Result:
java.util.ArrayList : [uno, due, tre] java.util.Vector : [uno, due, tre] java.util.Stack : [uno, due, tre] java.util.LinkedList : [uno, due, tre] java.util.PriorityQueue : [due, tre, uno] java.util.HashSet : [due, tre, uno] java.util.LinkedHashSet : [uno, due, tre] java.util.TreeSet : [due, tre, uno]
Opposite of removeAll(...)
, retainAll(...)
keeps only the elements in the Collection
that are contained in the parameter Collection
. It'll removes other elements that not part of the parameter Collection
.
private void retainAllFromCollection(Collection collection) { Collection anotherCol = new PriorityQueue(); anotherCol.add("uno"); anotherCol.add("tre"); anotherCol.add("cinque"); collection.retainAll(anotherCol); System.out.println(collection.getClass().getName() + " : " + collection); } ... app.retainAllFromCollection(colAL); app.retainAllFromCollection(colV); app.retainAllFromCollection(colS); app.retainAllFromCollection(colLL); app.retainAllFromCollection(colPQ); app.retainAllFromCollection(colHS); app.retainAllFromCollection(colLHS); app.retainAllFromCollection(colTS);
Result:
java.util.ArrayList : [uno, tre] java.util.Vector : [uno, tre] java.util.Stack : [uno, tre] java.util.LinkedList : [uno, tre] java.util.PriorityQueue : [tre, uno] java.util.HashSet : [tre, uno] java.util.LinkedHashSet : [uno, tre] java.util.TreeSet : [tre, uno]
Working with Collection
There are some common methods when working with a Collection
- boolean contains(Object o): check if this collection contains the specified element.
- boolean containsAll(Collection<?> c): check if this collection contains the elements in the parameter collection.
- boolean isEmpty(): check if this collection contains no elements.
- int size(): get the number of elements in this collection.
Let's check below example for contains(...)
and containsAll(...)
:
Collection list = new LinkedList(); list.add("red"); list.add("green"); list.add("blue"); System.out.println("List : " + list); System.out.println("List contains green?: " + list.contains("green")); Collection set = new TreeSet(); set.add("red"); set.add("green"); System.out.println("Set : " + set); System.out.println("List contains set? : " + list.containsAll(set)); set.add("black"); System.out.println("Set : " + set); System.out.println("List contains set? : " + list.containsAll(set));
The result is:
List : [red, green, blue] List contains green?: true Set : [green, red] List contains set? : true Set : [black, green, red] List contains set? : false
contains(...)
returns true since it have green in the collection. containsAll(...)
returns true when checking if the collection contains green and red. It returns false in the next checking, because not containing black.
Use size()
to check collection's size, and use isEmpty()
to check if collection is empty or not.
Collection al = new ArrayList(); System.out.println("ArrayList size : " + al.size() + ", isEmpty?: " + al.isEmpty()); al.addAll(list); System.out.println("Add to ArrayList : " + list); System.out.println("ArrayList size (now): " + al.size() + ", isEmpty?: " + al.isEmpty());
Result:
ArrayList size : 0, isEmpty?: true Add to ArrayList : [red, green, blue] ArrayList size (now): 3, isEmpty?: false
How to iterate over a Java Collection
There are several ways to iterate through a Collection in Java. The first way, using for each loop:
Collection pq = new PriorityQueue(); pq.addAll(al); System.out.println("Loop PriorityQueue:"); for (Object obj : pq) { System.out.println(obj); }
With result:
Loop PriorityQueue: blue red green
The second is using iterator. We iterate as long as hasNext()
is true, and each element is obtained using next()
method. To iterate, we can use while
or for
:
System.out.println("Iterate PriorityQueue using Iterator:"); System.out.println("Using while >>>"); Iterator it1 = pq.iterator(); // while while (it1.hasNext()) { System.out.println(it1.next()); } System.out.println("Using for loop >>>"); // for loop for (Iterator it2 = pq.iterator(); it2.hasNext();) { System.out.println(it2.next()); }
Result:
Iterate PriorityQueue using Iterator: Using while >>> blue red green Using for loop >>> blue red green