What are Java Collections? Get started with the framework
Tags: java, programming, computerscience, programmer
Published: 2021-04-30 18:11:49

Collections are used in every programming language. They are objects that group multiple elements into a single unit. Before the Collections Framework, it was hard for programmers to write algorithms that worked for different kinds of collections. Java came with some Collection classes, like *Vector*, *Stack*, *Hashtable*, and *Array*, but they had their disadvantages. 

In JDK 1.2, Java developers introduced the Collections Framework, which is an important framework to help you achieve all of your data operations. Today, we’ll dive deeper into this framework and some of its components.

**Here’s what we’ll cover today**: 
* [What are Java Collections?](#javacollections)
* [ArrayList in Java](#arraylist)
* [LinkedList in Java](#linkedlist)
* [HashSet in Java](#hashset)
* [TreeSet in Java](#treeset)
* [Other collections to study](#othercollections)
<br>

<a name="javacollections"></a>
## What are Java Collections?

The Java Collections Framework is a **unified architecture for representing and manipulating collections**. It contains interfaces, their implementation classes, and algorithms to process the data stored in a collection. The Collection interface is **extended by other interfaces** like List, Set, and Queue.

> **Note**: There’s also a Map interface, but it doesn’t implement the Collection interface because it stores key-value pairs, and the classes that come under the Collection interface only store values.

**Differences between the Collections Framework and Collections**:

* The Collections Framework is an interface, while Collections is a class.
* The Collection interface gives the standard functionality of data structures to *List*, *Set*, and *Queue*. The Collections class provides standard methods that you can use to search, sort, and coordinate collection elements.
* Collections are objects that represent a group of objects (like *Vector*), while the Collections Framework can represent and manipulate collections.

### The Java Collections Framework components

#### Interfaces

These interfaces supply the abstract data type to represent the collection. The `java.util.Collection` is the root interface of the framework. It's at the top of the framework hierarchy and contains important methods, like `size()`, `iterator()`, `add()`, `remove()`, and `clear()`.

The iterable interface is the root of the whole collection framework. It allows the iterator to iterate through all of the collections. All classes and interfaces use this interface. The collection interface extends the iterable interface and is executed by the classes in the collection framework. The list interface inhibits a list-type data structure where we can store ordered collections of objects.

Some more important interfaces include:
* Map interface: `java.util.Map`
* Set interface: `java.util.Set`
* Deque interface: `java.util.Deque`

> **Note**: The Map interface is the only one that doesn't inherit from the Collection interface, but is included in the Collections Framework. All framework interfaces are in the java.util package.

#### Implementation classes 

The framework provides implementation classes for collections. You can use them to create different types of collections in your Java programs. 
Some of the main collection classes include:

* `ArrayList`
* `LinkedList`
* `PriorityQueue`
* `HashMap` and `HashSet`
* `TreeMap` and `TreeSet`

#### Algorithms 

These algorithms perform important functions on collections, like sorting lists.

The Collections Framework hierarchy is as follows:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ylb3lp6va8on7j2fr23.png)

<br> 
<a name="arraylist"></a>

## ArrayList in Java

[ArrayList](https://www.educative.io/blog/java-arrays-tutorial-delcare-initialize#types) is the **most commonly used implementation of the List interface**. Some of its features include:

* Stores elements in insertion order
* Allows for storage of duplicate elements
* Supports null elements

An ArrayList **stores data in a resizable array**. When you create an ArrayList, you create an array of size zero. When the first element is inserted, the array size changes to ten. This is known as *lazy initialization* and it saves a lot of memory. Before adding an element to an ArrayList, the capacity is checked. If the array is full, then a new array of size (n + n/2 + 1) is created. The elements from the old array are then copied to the new one. 

**There are three ways to create an ArrayList in Java**:

#### 1. The no-arg constructor

This constructor doesn't take any arguments and will create a list size of zero.

```
List list = newArrayList();
```

#### 2. The constructor that takes initial capacity

You can give an initial capacity when creating an ArrayList. Let's say you know that your ArrayList will contain a minimum of 50 elements. You can create your ArrayList with a size of 50, reducing the need for constant resizing.

```
List list = newArrayList(50);
```

#### 3. Existing Collection

You can create an ArrayList using an existing Collection, and the list will contain all the elements in the original collection in the same order.

```
List list = newArrayList(oldList);
```

Here's an example of an ArrayList you could execute in Java:

```
import java.util.ArrayList;
import java.util.List;
public class ArrayListDemo {
    public static void main(String args[]) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        System.out.println(list);
        System.out.println("The element at index two is " + list.get(1));
        System.out.println("The size of the List is " + list.size());
    }
}
```
> **Output**:
 
> [1, 2, 3]
> The element at index two is 2
> The size of the List is 3

There are many things you can do with an ArrayList, including:

* Update an element using the `set(int index, E e)` method
* Check if an element is present using the `contains(Object o)` method
* Remove all elements within a given Collection using the `removeAll(Collection<?> c)` method
* Replace all elements using the `replaceAll(UnaryOperator<E> operator)`
* Etc.
<br>

<a name="linkedlist"></a>
## LinkedList in Java

The LinkedList class **implements the List and Deque interfaces**. Some of its features include:

* Stores elements in insertion order
* Supports duplicate elements
* Allows any number of null elements

LinkedList also has a static inner class called `Node`, which contains three fields:

1. `item`: contains the value of the current element
2. `next`: contains the pointer to the next element
3. `prev`: contains the pointer to the previous element]

**When an element is added to a LinkedList, it creates a new `Node` instance**. The prev and next fields are set depending on where the new node is added.
 
**There are two ways to create a LinkedList in Java**:

#### 1. The no-arg constructor

This constructor doesn't take any arguments and will create a list size of zero.

```
List<Integer> list = new LinkedList<Integer>();
```

#### 2. Existing Collection

You can create a LinkedList using an existing Collection, and the list will contain all the elements in the original collection in the same order.

```
List<Integer> list = new LinkedList<Integer>(oldList);
```

Here's an example of a LinkedList you could execute in Java:

```
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class LinkedListDemo {
    public static void main(String args[]) {
        LinkedList<Integer> linkedList = new LinkedList<>();
        linkedList.add(1); // Adds 1 to the list.
        linkedList.add(2); // Adds 2 to the end of the list.
        linkedList.addLast(3); // Adds 3 to the end of the list.
        System.out.println(linkedList);
        linkedList.addFirst(10); // Adds 10 to the start of the list.
        System.out.println(linkedList);
        linkedList.add(2, 20); // Adds 20 to second position in the list.
        System.out.println(linkedList);
        List<Integer> list = new ArrayList<>();
        list.add(101);
        list.add(102);
        list.add(103);
        linkedList.addAll(3, list); // Adds the collection of elements at third position in the list.
        System.out.println(linkedList);
    }
}
```

> **Output**: 

> [1, 2, 3]
> [10, 1, 2, 3]
> [10, 1, 20, 2, 3]
> [10, 1, 20, 101, 102, 103, 2, 3]

Some more things you can do with LinkedList:

* Fetch an element at a particular index using the `get(int index)` method
* Remove the last element using the `removeLast()` method
* Sort a LinkedList using the `sort()` method
* Etc.
<br>

<a name="hashset"></a>
## HashSet in Java

HashSet is a class in the `java.util` package which **implements the Set interface**. Some of the features of the HashSet include:

* Doesn't allow duplicate elements
* Only allows one null element
* Elements are inserted in a random order
* Internally backed by a HashMap

**There are four ways to create a HashSet in Java**:

#### 1. The no-arg constructor

This will create a HashSet with an initial capacity of 16 and a load factor of 0.75.

```
Set<Integer> set= new HashSet<>();
```

#### 2. A constructor that takes initial capacity

If you know your HashSet will have more than 16 elements, you can set a higher initial capacity to reduce the need for resizing. It will use a default load factor of 0.75.

#### 3. A constructor that takes initial capacity and load factor

You can also provide an initial load factor along with an initial capacity.

#### 4. A constructor that takes another Set as a parameter

You can create a HashSet using another Set by passing it to the constructor. It will have the same size as the passed set and a default load factor of 0.75.

Here's an example of a HashSet you could execute in Java:

```
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo {
    public static void main(String args[]) {
        Set<Integer> set = new HashSet<>();
        System.out.println("Inserting 17 in the HashSet:  " + set.add(17));
        System.out.println("Inserting 34 in the HashSet:  " + set.add(34));
        System.out.println("Inserting 17 in the HashSet:  " + set.add(17));
        System.out.println(set);
    }
}
```

> **Output**:

> Inserting 17 in the HashSet:  true
> Inserting 34 in the HashSet:  true
> Inserting 17 in the HashSet:  false
> [17, 34]

The above code showed a demonstration of the `add(E e)` method that inserts an element into the HashSet. If the inserted element wasn't already in the HashSet, the method returned `true`. If the element was already in the HashSet, the method returned `false`.

There's more you can do with HashSets, like:

* Remove elements using the `remove(Object o)` method
* Check if the HashSet is empty using the `isEmpty()` method
* Fetch an element from a HashSet using the `contains()` method
* Etc.
<br>

<a name="treeset"></a>
## TreeSet in Java

The TreeSet class **implements the Set interface** that uses a [tree](https://www.educative.io/blog/data-structures-trees-java) for storage. Some of the features include:

* Doesn't allow duplicate elements
* Doesn't allow null elements
* Quick access and retrieval times 
* Elements stored in ascending order

The TreeSet hierarchy is as follows:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5nwi137dfjyr0sh8epsl.png)

> **How is a TreeSet different from a HashSet?**
> * HashSet allows one null element, while TreeSet doesn't allow any
>* Elements are sorted randomly in HashSet, while they are sorted in order in TreeSet
>* HashSet is faster for operations like add, remove, contains, size, etc.

**There are four ways to create a TreeSet in Java**:

#### 1. The no-arg constructor

```
Set<Integer> set = new TreeSet<>();
```

#### 2. A constructor with Comparator as an argument

If the objects you store in your TreeSet don't implement the Comparator interface or if you need to store the elements in descending order, you can provide a custom Comparator while creating a TreeSet, which will sort the elements per the logic of the Comparator.

#### 3. A constructor with the Collection type argument

You can create a TreeSet from another Collection. The elements will be stored in ascending order.

#### 4. A constructor with the argument of type SortedSet

This constructor acts as a copy constructor and creates a new sorted set with the same elements and the same order of the provided sorted set.

Here's an example of a TreeSet you could execute in Java:

```
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetDemo {
    public static void main(String args[]) {
        TreeSet<Integer> set = new TreeSet<>();
        set.add(21);
        set.add(32);
        set.add(44);
        set.add(11);
        set.add(54);
        System.out.println("TreeSet elements in ascending order " + set);
        // This TreeSet will store the elements in reverse order.
        TreeSet<Integer> reverseSet = new TreeSet<>(Comparator.reverseOrder());
        reverseSet.add(21);
        reverseSet.add(32);
        reverseSet.add(44);
        reverseSet.add(11);
        reverseSet.add(54);
        System.out.println("TreeSet elements in descending order " + reverseSet);
    }
}
```

> **Output**:

> TreeSet elements in ascending order [11, 21, 32, 44, 54]
> TreeSet elements in descending order [54, 44, 32, 21, 11]

There are more things you can do with TreeSet, such as:

* Fetch elements greater than the given element using the `tailSet(E fromElement)` method
* Fetch a subset of elements using the `subSet(E fromElement, E to Element)` method
* Etc.
<br>

<a name="othercollections"></a>
## Other collections to study

Congratulations on taking your first steps with the Java Collections Framework! Collection is one of the most important topics in Java programming, and this important framework will help you accomplish all of your data operations. You’re now ready to dive deeper into the Java Collections Framework and learn about more topics such as:

* LinkedHashMap and LinkedHashSet
* SortedMap and SortedSet
* toArray()
* hasNext()
* Etc.

To get started learning more about the Java Collections Framework, check out Educative’s course, [**Collections in Java**](https://www.educative.io/courses/collections-in-java). This curated, hands-on course covers all the collection types available in the Collections Framework. You’ll cover the internal workings of each Java collection so you can work with them more efficiently. The skills you gain in this course will give you an edge in Java-based interviews.

*Happy learning!*
<br>

### Continue reading about Java

* [Java 8 Tutorial: master stream API and beyond](https://www.educative.io/blog/master-stream-api-and-beyond)
* [Arrays in Java Tutorial: how to declare & initialize Java arrays](https://www.educative.io/blog/java-arrays-tutorial-delcare-initialize)
* [Java interview prep: 15 Java interview questions](https://www.educative.io/blog/15-java-interview-questions)