A collection is a group of elements (E). Java uses the Collection interface to define the properties and behavior of various collections. This interface is part of the java.util package. Therefore, you do not need to explicitly import the Collection interface.
This interface provides a number of useful sub interfaces whose classes you’ll be working with, such as: Deque, List, Queue, Set, and SortedSet. In order for you to use a collection, you’ll have to interact with one of these sub interfaces and not the collection interface.
We will discuss how to use collections in Java below.
Read: What are Java Interfaces?
Collections in Java
As mentioned earlier, all collections in Java inherit from Collection. For that reason, it is important for developers to know some of the methods Collection has, since the sub interfaces (and implementing classes) use these methods.
Here are some of the important methods used by Collection:
- add(E e): adds an element to the given collection
- contains(Object o): checks if the collection contains a given Object. Returns a boolean value
- remove(Object o): removes one instance of the given object. Note that, depending on the type of collection, multiple instances of the same object may be allowed
- size(): returns the number of elements in the collection
- toArray(): converts the collection elements into an array and returns an object array (Object[])
Lists in Java
In Java, a list is an ordered group of elements. List elements begin from index 0 to n-1, similar to array. A list can accept different types of elements, including null elements and even other lists.
However, it is important to mention that when a list is part of the elements in a list, then the equals() and hashCode() may not behave as expected.
This section will discuss some of the commonly used classes which implement the List interface, including: ArrayList, LinkedList, and Stack.
An ArrayList is a dynamic array, which can be very helpful when developers need an array whose size may change during manipulation.
A LinkedList is a linear data structure where each node is connected to the next. A node is a two-part value consisting of an element and the pointer to the next element.
A Stack is a linear data structure that uses the LIFO (Last In First Out) principle to remove elements. It provides two useful methods. The first adds an element to the top of the list (push(E item)) and the second – pop() – removes the first element in the list.
Here is a Java code example that uses an ArrayList to store integer heights. It then sorts the list and stores the result in Stack:
import java.util.*; class Height{ public static void main(String[] args) { int[] a = {8, 2, 5, 7, 1, 6, 3}; //heights in meters ArrayList heights = new ArrayList(); Stack heightsAscending = new Stack<>(); for(int i =0; i< a.length; i++){ if( a[i] > 0){ heights.add(a[i]); } } Object[] Obj = heights.toArray(); Arrays.sort(Obj); for(int i=0; i< Obj.length; i++ ){ heightsAscending.add(Obj[i].toString()); } System.out.println(heightsAscending); } }
There are other types of lists that the Java API provides, including AbstractList, RoleList, and Vector. You can learn more about them from Oracle’s Collection API docs.
Read: Top Online Courses to Learn Java
How to Use Queue and Deque
A queue is a linear data structure which uses the FIFO (First In First Out) principle. That is, the first element in the list is the first to be removed using the remove() method. A queue is similar to a stack in structure. The main difference is that a queue uses the FIFO principle while a stack uses LIFO. You can add an element at the end of the using queue using the add(E e) method.
A Deque (short for “double ended queue”) is a queue that allows adding and removing elements on either end of the queue. Here are some useful deque methods:
- addFirst(E e): add an element at the head of the deque
- addLast(E e): adds an element at the end of the deque
- remove(): removes the first element of the deque
It is worth noting that Deque is a subinterface of Queue, and, therefore, each deque has a queue which represents it.
In order to use a queue in your program, you need to use one of the available implementations. They are grouped into two categories:
- General-purpose: In this category, programmers can use the PriorityQueue class. Elements in this class are queued according to natural ordering, with the smallest element at the head.
- Concurrent implementations: These are synchronized implementations. That is, they wait for the queue to have space before adding an element or to have an element(s) before retrieving it. The classes in this category implement the BlockingQueue interface, which has the properties that have just been described.
Here are two classes that implement BlockingQueue:
- ArrayBlockingQueue: This is a blocking queue that uses an array of a fixed size. It has a constructor that allows you to set an integer value to bound its capacity.
- PriorityBlockingQueue: This blocking queue is unbounded and elements are ordered in the same way as the PriorityQueue.
A key point to note is that a priority queue is unbounded while a blocking queue can be bounded.
Final Thoughts on Java Collections
In this programming tutorial, we learned about the various collections defined in the Java API. Remember, collections define groups of elements. The particular association you would like your elements to have defines the exact collection implementation to choose.