Working with arrays of data and their structuring, searching for correspondences between them, filtering—all of this is the basis of any program written in Java. This is why it is essential for programmers to have tools in their arsenal that make working with this data as easy and structured as possible. This is where collections of Java frameworks come into play.
This is a set of different interfaces for working with groups of objects in Java programming. Collections allow you to manipulate arrays, queues, lists, maps, and other object types.
All collections in Java are strictly structured: some interfaces subordinate others, while the latter extends the functionality of their "big brothers" in the hierarchy.
The hierarchical structure of the Java Collections Framework is based on the Collection interface, which is the overarching interface. A general collection accommodates all other types of collections and allows you to work with groups of objects thanks to the main methods, which include:
add(…);
remove(…);
clear(…).
The Collection interface inherits from Iterable, which means that all collections subordinate to it are iterable regardless of their implementation type. Because of this, you can get an iterator in Collection that allows you to iterate through other collection interfaces.
The Collection interface has three primary interfaces:
Set - allows you to work with data sets
List - interacts with lists of data
Queue - works with queue
The Map interface works with key-value data. It's listed separately, and I'll explain later why that's the case. For now, let's go through the main types of collections and find out what each is responsible for.
A list is an ordered collection, most commonly used in the Java Collections Framework. This interface controls where each list item is inserted. When working with List, the user accesses list items by their integer index (position in the list).
The List interface has two standard implementations: ArrayList and LinkedList.
The point is that you can write other implementations, but the JDK already has two that are available out of the box.
ArrayList contains an array whose length will increase automatically when new elements are added to it.
The second implementation of the List interface is the LinkedList class. This is a list with two links, where each element contains a link to the preceding and the following elements of the list.
ArrayList and LinkedList are identical; that is, their methods are exactly the same. They can both add and extract elements from any part of the list. So what's the difference? The main difference between them is the cyclomatic complexity of operations—the number of linearly independent routing points that pass through the program code. The smaller the number of route points each individual command passes through, the faster the program will run.
To illustrate the differences in cyclomatic complexity between the two classes, consider this table:
As you can see, the main advantages of the LinkedList class are related to the operations (iterator.remove() and ListIterator.add(E element). Their cyclomatic complexity will always be O(1). In case of add(E element) it is better to use LinkedList, but for get(int index), ArrayList is better.
The same applies to the add(int index, E element) operator. The cyclomatic complexity of this operation for LinkedList is lower only if the index itself is zero. For all other cases, it is more reasonable to use ArrayList.
The same applies to the remove operation: for the LinkedList class, its cyclomatic complexity will be half as much as for ArrayList. Looking ahead, it is ArrayList that is used in the vast majority of the List interface operations.
Set is a collection that contains no repeating elements. This interface is designed to model abstractions of a mathematical set.
The Set hierarchy includes two interfaces, SortedSet and NavigableSet, and three main classes. I will describe the latter in more detail:
HashSet is a collection that does not allow storage of identical elements due to the HashMap object it contains. It uses hash tables to store data.
LinkedHashSet is similar to a HashSet, in which the elements are combined with each other in an ordered list. In this case, the elements are stored in the same order in which they are added (due to the LinkedHashMap object's contents).
TreeSet is a collection that uses a value-ordered tree to store items. TreeSet contains TreeMap, a collection that uses a balanced red-black binary tree to store its elements. Because of this, the add, remove and contains operations in this collection take a guaranteed time equal to log(n). This is a significant advantage over other implementations of the Set interface.
We all don't like queues—who likes wasting their time waiting for something? But you will definitely like queues if you learn how to work with them 🙂 In Java Collections Framework the Queue interface is responsible for working with queues, which has a reasonably simple hierarchy: The queue can order the elements in the queue according to two basic types:
This is a collection designed to handle key-value data. By key, we mean the object we use to retrieve the data it contains. Structurally, Map does not inherit the Iterable collection and has several unique methods that are unique to it.
This interface has a class hierarchy similar to Set. Map is implemented using four implementations: HashMap, TreeMap (I wrote about this above), LinkedHashMap, and WeakHashMap:
Collections in Java are pretty extensive. They contain a lot of interfaces and implementations, each of which deserves its own article.
At the same time, the Java Collections Framework includes all the functionality needed to write multitasking code of any complexity.
A proper understanding of the principles of working with collections will remain one of the primary skills for quality Java programming. NIX United, a Florida-based software development company, has in its team experienced Java programmers that would be happy to answer your questions regarding Java Collections Framework.