Welcome to a complete Guide to Java Collections Framework. You will learn basic hierarchy of Java Collections, Collection Types, their features and the recent modifications to the Framework all along with detailed examples.
Java Collections Framework ?
A Collection represents group of Objects. You can use collections to store datasets in the form of objects. Collections stores objects of similar types. Although you may store different types of objects in a collection. But, in that case those objects belong to a common type of Object. The objects your store in a collection are called as elements.
Before we go further, it is important to understand what is an Array. Certainly, almost all general programming languages including Java support arrays. Arrays are nothing but collection of related or unrelated data. Also, they have fixed size and fixed memory locations. While, each memory location is identified with a sequential index. You use the index to add, modify or remove respective element from an array.
Arrays are the base of Java Collections Framework. However, Java Collections Frameworks, based on different requirements provide different types of collections. Hence, you get a choice to use a very specific type of collection that is based on your data and requirement. For example, some of the collections have indexes and some of them store elements in key value pattern. Some do support sorting or maintain order of insertion, while other do not.
Basic Components of a Collection
In this section you will learn what are the basic components of any Collection.
- Interface: Interfaces provides a type to a Collection. They mandates certain behaviour to be maintained by each concrete implementations. However, they also allow the collection implementations to have liberty of providing or changing implementation without changing the consumer.
- Implementations: These are the actual implementation of the collection types. For example, the ArrayList, or HashSets are the actual implementations of List and Set interfaces respectively.
- Algorithm: Algorithms are used by the interface methods. The algorithms come into picture when sorting, or searching a collections. Also, various methods of various interfaces may reuse the algorithms.
All of these three things decide if a Collection is Good for your use case.
Collections Framework Advantages
Before we jump on to the details of Collections Framework, let’s understand why should be use one. Below are some of the benefits Collections provides.
- Less Efforts: Java Collections Framework provide data structures with pre-implemented algorithms. You don’t have to write your own algorithms.
- Performance: Java Collections framework provides different types and implementations. Moreover, it ensures the algorithms are optimal for the general purpose usage. Hence, you get great performance with Collections.
- Variety: When we discuss the collections framework advantages we should also look at the different types of collections and implementation it provides. For example, Linked List, ArrayList, HashSet, TreeSet etc.
The Java programming language provides many different types of Collections. Java has provided Collection interface, which is the super interface of the hierarchy. In other words, all the other collections interfaces and implementation inherit this super interface.
This interface defines some of the basic methods to work with collections. These methods includes methods to add, remove, modify, check and read elements from a collection. Before we go further, let’s have a look at some to the basic methods from Collection interface.
Methods of Collection Interface
- boolean add(E e): Adds given element to the collection.
- boolean addAll(Collection<? extends E> e): Adds all the elements in given collections to the collection.
- void clear(): Removes all the elements from the collection.
- boolean contains(Object o): Returns true if given element is present in the collection.
- boolean containsAll(Collection<?> o): Returns true if the given elements of the given collection are present.
- boolean isEmpty(): True if empty.
- Iterator<E> iterator(): Returns an instance of Iterator. Which is used to iterate through the collection.
- boolean remove(Object o): Removes an element which is equals to the given element.
- boolean removeAll(Collection<?> c): Removes all the elements.
- boolean retainAll(Collection<?> c): Removes everything except the elements of given collection.
- int size(): Returns the size of the collection.
- Object toArray(): Converts the collection to an array.
- <T>T toArray(T a): Converts the collections to an array of type of given array. Moreover, It returns the same array if the collection elements fit into the given array. Otherwise, it populates and returns a new array of the same type.
Default Methods in Collection Interface
Apart from above methods, there are three default methods in the interface.
- default Stream<E> parallelStream(): Creates and returns a parallel stream from the collection.
- default boolean removeIf(Predicate<? super E> filter): Removes all the elements from the collection that satisfy the given predicate.
- default Spliterator<E> spliterator(): Creates and returns a Spliterator on the given collection.
- default Stream<E> stream(): Returns a sequential stream from the collection.
You should note that these are just default methods. Java has added these methods for the backward compatibility after the introduction of Java 8 Streams API.
Read more about Java Default Methods and examples.
Java Collection Types
By now, you are familiar with the Collection interface. However, it was just an interface with number of methods. As stated earlier, Java Collection Framework has number of interfaces and concrete implementations. Because of which Java can provide various types of Collections for very specific requirements. At this time, we will look into these implementations.
List is a sub-Interface in the Collection hierarchy. Firstly, Lists are sequential collections and it store each element at sequential index positions. Because of which, with the index, the user can access and element directly.
In short, Lists are sequential, unsorted, and by-default non-unique collections. The List implementations use arrays internally and specifically ArrayList is very much similar to an array. However, lists do grow dynamically, while arrays do not. Hence, you can use List implementations for any specific requirement or as a general purpose collection.
Java provides below implementations of List types.
Set is also a sub-interface and a type of Java Collections. Unlike Lists, Sets are not sequential collections. In other words, Sets do not store elements based on index positions. Hence use has to iterate through the entire collection to access one or more elements.
In short Sets are unsorted, unordered, unique collections. The Sets ignore any duplicate insertions. Because of this, you can use Sets for any datasets where sequence is not important or if you want to remove duplicates.
Set has below pre-defined implementations.
Queue is a type of Data Structure, that resembles a tube with two ends. In general, Queues are First In First Out (FIFO). In other words, with queues you can insert an element from one end and remove from the other. Also, considering it’s tube like structure the element which was inserted first will be first to come out.
However, in Java the Queue implementations differ from the concept of FIFO for good. Java Queue implementations and implementations of its child interfaces provide convenience methods. For example,
PriorityQueue. With these queues you can pass your own comparator or let the queue return objects in their natural order. Hence the PriorityQueue difference from the concept of FIFO.
You can use queues for storing the elements before processing. The best suited example is an event driven architecture. Where the processors process the events asynchronously. You can have the provider pushing events in a queue and one or more consumers asynchronously polling from the queue.
With a Deque you can insert and remove elements from both of the ends. Otherwise, it is almost same as the Queue. The Deque interface in Java extends from Queue interface.
The Deque is actually stands for Double Ended Queue because it is open on both of the ends. You can perform the operations like insert, remove, peek on both of the sides of a Deque. The Deque provides two versions of all the operations, where one version results in an exception and the other returns null or false. You can use the version which returns null or false in the case of capacity restricting Deque.
You can use Deque, as an alternative to Stack which is a Last In First Out (FIFO) type data structure. In other words, both insert, peek and remove all performed on the same end of Deque.
In this tutorial you learned about Java Collections Framework. Collection is an interface in Java and is a parent interface. All the other implementations and sub-interfaces are derived from this interface.
Java Collections come in many different types and you can chose the best fitting implementation for your requirements.