Collections in Kotlin


Collections are a common concept for most programming languages. It is a way of storing similar data types in a single object and iterate over it. Similar to any other language, Kotlin also has Collection defined in kotlin.collections package.

Types of Collection in Kotlin

There are two types of collection in Kotlin

  1. Immutable
    The one which can't be modified once the object is created. We can just iterate over them or create a copy of them but we can't modify the actual one.

  2. Mutable
    These can be modified means that we can add items or elements to the original object once they are created along with iteration and copy.
To understand the immutable and mutable types, Let's try to understand the interfaces in the Collection package of Kotlin first.

Keep in mind we are only talking about the interfaces and implementations of Kotlin. Although, Android is compatible with Java also and we can use the Collections of Java also defined in java.util package but Kotlin has a separate Collection and a few of the implementations like Vector, CopyOnWriteArrayList, CopyOnWriteArraySet and many more are not there in Kotlin.


Collections in Kotlin

Iterable

The parent of all the interfaces is Iterable. As the name suggests, it confirms the functionality of iteration by the class which implements it. This has an abstract function iterator that returns the Iterator reference object.
  
/**
* Classes that inherit from this interface can be represented as a sequence of elements that can
* be iterated over.
* @param T the type of element being iterated over. The iterator is covariant on its element type.
*/
public interface Iterable<out T> {
/**
* Returns an iterator over the elements of this object.
*/
public operator fun iterator(): Iterator<T>
}

MutableIterable

Iterable is further extended by another interface ie MutableIterable. This particular interface confirms the iteration along with the mutability. This means the object can be mutated or modified.
  
/**
* Classes that inherit from this interface can be represented as a sequence of elements that can
* be iterated over and that supports removing elements during iteration.
* @param T the type of element being iterated over. The mutable iterator is invariant on its element type.
*/
public interface MutableIterable<out T> : Iterable<T> {
/**
* Returns an iterator over the elements of this sequence that supports removing elements during iteration.
*/
override fun iterator(): MutableIterator<T>
}

Collection

The Iterable is also extended by the Collection interface which provides the basic functions like size, isEmpty, contains and containsAll.
  
/**
* A generic collection of elements. Methods in this interface support only read-only access to the collection;
* read/write access is supported through the MutableCollection interface.
* @param E the type of elements contained in the collection. The collection is covariant on its element type.
*/
public interface Collection<out E> : Iterable<E> {
// Query Operations
/**
* Returns the size of the collection.
*/
public val size: Int

/**
* Returns `true` if the collection is empty (contains no elements), `false` otherwise.
*/
public fun isEmpty(): Boolean

/**
* Checks if the specified element is contained in this collection.
*/
public operator fun contains(element: @UnsafeVariance E): Boolean

override fun iterator(): Iterator<E>

// Bulk Operations
/**
* Checks if all elements in the specified collection are contained in this collection.
*/
public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean
}

MutableCollection

MutableIterable and Collection are further extended by MutableCollection which provides mutability to the Collection like add, remove, addAll, removeAll, retainAll, clear.
  
/**
* A generic collection of elements that supports adding and removing elements.
*
* @param E the type of elements contained in the collection. The mutable collection is invariant on its element type.
*/
public interface MutableCollection<E> : Collection<E>, MutableIterable<E> {
// Query Operations
override fun iterator(): MutableIterator<E>

// Modification Operations
/**
* Adds the specified element to the collection.
*
* @return `true` if the element has been added, `false` if the collection does not support duplicates
* and the element is already contained in the collection.
*/
public fun add(element: E): Boolean

/**
* Removes a single instance of the specified element from this
* collection, if it is present.
*
* @return `true` if the element has been successfully removed; `false` if it was not present in the collection.
*/
public fun remove(element: E): Boolean

// Bulk Modification Operations
/**
* Adds all of the elements of the specified collection to this collection.
*
* @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified.
*/
public fun addAll(elements: Collection<E>): Boolean

/**
* Removes all of this collection's elements that are also contained in the specified collection.
*
* @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified.
*/
public fun removeAll(elements: Collection<E>): Boolean

/**
* Retains only the elements in this collection that are contained in the specified collection.
*
* @return `true` if any element was removed from the collection, `false` if the collection was not modified.
*/
public fun retainAll(elements: Collection<E>): Boolean

/**
* Removes all elements from this collection.
*/
public fun clear(): Unit
}

List

List is an ordered collection where we can access the elements by indices. List interface is extended by Collection interface.

MutableList

MutableList is also an ordered collection where we can access the elements by indices but this is mutable. This means we can modify the object created, we can add remove elements it in. MutableList is extended by MutableCollection interface.

Set

Set is an unordered collection of unique elements. The order of insertion of elements or items is not maintained in Set. It is extended by Collection interface.

MutableSet

MutableSet is also an unordered collection of unique elements but this is mutable. The order of insertion of elements or items is also not maintained in MutableSet. It is extended by MutableCollection interface.

Map

Map is a set of key-value pairs where Keys are unique, and each of them maps to exactly one value. The values can be duplicates but the keys will be unique. The order of insertion of elements or items is not maintained in the map also. Map is immutable means we can't modify the object(add or remove elements) once it's created.

This has no connection with any of the above interfaces but this has two objects, keys and values which are of types Set and Collection respectively.
  
/**
* A collection that holds pairs of objects (keys and values) and supports efficiently retrieving
* the value corresponding to each key. Map keys are unique; the map holds only one value for each key.
* Methods in this interface support only read-only access to the map; read-write access is supported through
* the [MutableMap] interface.
* @param K the type of map keys. The map is invariant on its key type, as it
* can accept key as a parameter (of [containsKey] for example) and return it in [keys] set.
* @param V the type of map values. The map is covariant on its value type.
*/
public interface Map<K, out V> {

...

/**
* Returns a read-only [Set] of all keys in this map.
*/
public val keys: Set<K>

/**
* Returns a read-only [Collection] of all values in this map. Note that this collection may contain duplicate values.
*/
public val values: Collection<V>

...
}

MautableMap

MutableMap is similar to Map only which holds key-value but this is mutable. This also has no connection with any of the above interfaces.
Now that we have a clear picture of interfaces, lets look at how can we initialise the respective objects in Kotlin

Immutable and Mutable List

  
//Immutable Lists
val list = listOf(1, 2, 3)
val listOfNonNull = listOfNotNull(1, 2, 3)

//Mutable Lists
val arrayList = ArrayList()
val arrayList2 = arrayListOf(1, 2, 3)
val mutableList = mutableListOf(1, 2, 3)

Immutable and Mutable Set

  
//Immutable Sets
val set = setOf(1, 2, 3)

//Mutable Sets
val hashSet = hashSetOf(1, 2, 3)
val mutableSet = mutableSetOf(1, 2, 3)
val linkedSet = linkedSetOf(1, 2, 3)

Immutable and Mutable Map

  
//Immutable Maps
val map = mapOf(1 to "One", 2 to "Two", 3 to "Three")

//Mutable Maps
val hashMap = hashMapOf(1 to "One", 2 to "Two", 3 to "Three")
val mutableMap = mutableMapOf(1 to "One", 2 to "Two", 3 to "Three")
val sortedMap = sortedMapOf(1 to "One", 2 to "Two", 3 to "Three")


Reference: Kotlin docs