Kotlin Collections and how it compares with Java Collections API
Tags: kotlin, java, programming, collections
Published: 2019-06-23 14:33:11

---
title:Kotlin Collections and how it compares with Java Collections API
published: true
description:Kotlin Collections and how it compares with Java Collections API
tags: Kotlin, Java, Programming, Collections
cover_image: https://thepracticaldev.s3.amazonaws.com/i/vi5kbaqpzkdqelhii7a0.jpg
---

We developers usually write software that uses collections on a daily basis, code that deals with things such as fetching a list of products from the database, writing a set of data to a file like CSV among other things are quite common. So let’s take a look on how Kotlin Collections work and how do they compare to Java Collections API.

#Read-Only and Mutable collections

![](https://thepracticaldev.s3.amazonaws.com/i/71zsvcjyol7n9ctxzn5q.png)
<figcaption>Overview of collections interfaces</figcaption>


As you can see in this figure, Kotlin has a mutable counterpart which inherits and adds functions such as `fun add(element: E)` and `fun remove(element: E)` for every read-only interface. ArrayList, HashSet, LinkedHashSet, LinkedHashMap and HashMap classes are treated as implementations of MutableList, MutableSet and MutableMap respectively and they are very similar to the ones you find in Java Collections API, in fact, these are the same but marked as `typealias` by Kotlin, as seen in the [TypeAliases.kt runtime library file:](https://github.com/JetBrains/kotlin/blob/v1.3.31/libraries/stdlib/jvm/src/kotlin/collections/TypeAliases.kt)

``` kotlin
@SinceKotlin("1.1") public actual typealias ArrayList<E> = java.util.ArrayList<E>
@SinceKotlin("1.1") public actual typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
@SinceKotlin("1.1") public actual typealias HashMap<K, V> = java.util.HashMap<K, V>
@SinceKotlin("1.1") public actual typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
@SinceKotlin("1.1") public actual typealias HashSet<E> = java.util.HashSet<E>
```

#### Collections-creation functions

| Type                  | Function                    | Mutability
| :----:                |       :-------------:       |   :-----:
|  List                 |      `listOf()`             |   Read-Only
|  MutableList          |      `arrayListOf()`        |   Mutable
|  Set                  |      `setOf()`              |   Read-Only
|  MutableSet           |      `hashSetOf()`          |   Mutable
|  Map                  |      `mapOf()`              |   Read-Only
|  MutableMap           |      `hashMapOf()`          |   Mutable

These are the top-level functions used to create collections in Kotlin, example:

``` kotlin
    val list = listOf(1, 2, 3)
    val mutableArrayList = arrayListOf(1, 2, 3)
    val map = mapOf(1 to "one", 2 to "two") //key is an Int valued by a String
    val mutableHashMapOf = hashMapOf(1 to "one", 2 to "two")
    val set = setOf(1, 2, 3)
    val mutableHashSetOf = hashSetOf(1, 2, 3)
```

If we were to create an immutable List in Java, we would have to wrap our collection in another one like this:

``` java
    List<String> originalMutableList = new ArrayList<>();
    List<String> unmodifiableList = Collections.unmodifiableList(originalMutableList);
    // Collections.unmodifiableMap(...);
    // Collections.unmodifiableSet(...);
    // and so on... 
```

We still would have methods such as `add`, `remove` and `clear` tough, as it's part of the List interface and there's no such distinction between read-only and mutable lists in standard Java.

#### Filter, map, flatMap and zip

###### Filter

Filtering lists in Kotlin is simple and looks very similar to the way we work with Java 8 Streams, Kotlin's Iterable interface has a method named filter that accepts a predicate in order to process the collection.

``` kotlin
    
    val countries = listOf("Brazil", "Argentina", "Germany")
    val filteredCountries = countries.filter { it.length > 6 } 
    //'it' means the instance itself, in that case a String representing a country name

    println(filteredCountries) // prints [Argentina, Germany] 
``` 

###### Map and flatMap

Pretty much like filtering, Map and flatMap operations remain similar to the ones found in Java 8 when working with Streams.

Map:
``` kotlin
    
    val countries = listOf("Brazil", "Argentina", "Germany")
    val countriesToLowerCase = countries.map(String::toLowerCase) //same as countries.map { it.toLowerCase() }

    println(countriesToLowerCase) //prints [brazil, argentina, germany]
``` 

flatMap:

``` kotlin
    
    val countries = listOf("Brazil", "Argentina", "Germany")
    val listOfCharacters = countries.flatMap { it.toList() } // converts to a List of chars

    println(listOfCharacters) // prints [B, r, a, z, i, l, A, r, g, e, n, t, i, n, a, G, e, r, m, a, n, y]
```

zip:

``` kotlin

    val countries = listOf("Brazil", "Argentina", "Germany")
    val cities = listOf("Aracaju", "Ushuaia", "Berlin")

    val zippedPairs = cities.zip(countries) //creates a new list containing an ordered pair of the elements of these two lists

    println(zippedPairs) // prints [(Aracaju, Brazil), (Ushuaia, Argentina), (Berlin, Germany)]
```

**Please note that unlike Java 8 Streams, Kotlin Lists are eagerly evaluated, which means there's no need to use terminal methods such as collect(), forEach(), etc... to run intermediate operations.**

### Sequences

Sequences are like lazily evaluated collections, which means that when we invoke functions such as filter and map to it, these will add intermediate steps to be executed when requested, that is, when a _terminal_ function is called. Examples of terminal functions are `toList()`, `first()`, `sumBy()` and `max()`. Sequences are a good choice when the size of the collection is not known in advance, or when the collection is too large to be processed or kept in memory at once.

Despite the similarities, I'd favor Sequences over Streams as it offers a more idiomatic, homogeneous and cleaner code when working with Kotlin. 
Another important thing to keep in mind is that at the time of writing this article [Kotlin targets JDK 1.6+](https://kotlinlang.org/docs/reference/faq.html#does-kotlin-only-target-java-6), which means that if you are using Java 6 working with Sequences might be your only choice.

``` kotlin
    val cities = listOf("Aracaju", "Ushuaia", "Berlin")

    val sequence = cities.asSequence().filter { it.startsWith("A") }.map { it.toUpperCase() }

    println(sequence.first()) //prints ARACAJU
```

Kotlin is a pragmatic language created to solve real world problems, it aims to provide popular features that have proven to be successful. With collections, for instance, we have built-in well segregated components for both mutable and immutable concepts.

Hope you enjoyed, thanks a lot! (this is my first article by the way :D).