The Kotlin collections are actually direct instances of the collections in the JDK. There’s no conversion of wrapping involved. So, if you didn’t skimp on your study of collections while you were in Java, that will certainly come in handy now. Although Kotlin didn’t define its own collections code, it did add quite a few convenience functions to the framework, which is a welcome addition because it makes the collections easier to work with.

Before we go to the code examples and more details, something needs to be said why it is called a collections framework. The reason it’s called a framework is because the data structures are very diverse, in and of themselves. Some of them puts constraints on how we go through the collection, they impose certain order of traversal. Some of the collections constrains the uniqueness of the data elements, they won’t allow you to put duplicates. And some of them lets us work with the collections in pairs, like in a dictionary entry, you’ll have a key with a corresponding value.

.At the top of the hierarchy are the interfaces Iterable and MutableIterable — refer to the big image at the beginning of this article. They are the parents of all the collection classes we will work with. As you may have noticed in the diagram, each Java collection has two representations in Kotlin; a read-only one and a mutable one. The mutable interfaces map directly to the Java interfaces while the immutable interfaces lack all of the mutator methods of their mutable counterparts.

Kotlin doesn’t have a dedicated syntax for creating lists or sets, but it does provide us with library functions to facilitate creation. Table 1 lists some of them.

Table 1. creation functions for collections

Collection read only read-write
list listOf mutableListOf, arrayListOf
set setOf mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf
map mapOf mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf

List

A list is a type of collection that has a specific iteration order.  It means that if we added a couple of elements to the list, and then we step through it, the elements would come out in a very specific order — it’s the order by which they were added or inserted.  They won’t come out in a random order or reverse chronology, but precisely in the sequence they were added.  It implies that each element in the list has a placement order, an index number that indicates its ordinal position. The first element to be added will have its index at 0, the second will be 1, the third will be 2, so on and so forth. So, just like an array, it is zero-based

Set

Sets are very similar to lists, both in operation and in structure, so, all of the things we’ve learned about lists applies to sets as well. Sets differ from lists in the way it puts constraints on the uniqueness of elements.  It doesn’t allow duplicate elements or the same elements within a set. It may seem obvious to many what the “same” means, but Kotlin, like Java has a specific meaning for “sameness”.  When we say that two objects are the same, it means that we’ve subjected the objects to a test for structural equality. Both Java and Kotlin defines a method called equals() which allows us to determine equivalence relationships between objects.  This is generally what we mean by “sameness”. 

Map

Unlike lists or sets, maps aren’t a collection of individual values, but rather, they are a collection of pairs of values. Think of a map like a dictionary or a phone book, its contents are organized using a key-value pair. For each key in a map, there is one and only one corresponding value. In a dictionary example, the key would be the term, and its value would be the meaning or the definition of the term.

The keys in a map is unique. Like sets, maps do not allow duplicate keys. However, the values in a map are not subjected to the same uniqueness constraints , two or more pairs in map may have the same value

Collection Protocols

The Kotlin team probably didn’t refer to the set of actions you can do on collections as “collections protocol”, I just thought it would be cool to borrow the term from Python . Anyhoo, one of the benefits of working with the collections framework is that, your knowledge and skill on lists, for example, commutes nicely to sets and maps. This way, you learn a set of skills for one kind of collection and you can use it on the other two. This is one of the reasons it’s called a framework.

Table 2. Common things you can find or do in the collection classes

function or property description
size tells you how many elements are in the collection.  Works with lists, sets and maps
isEmpty() returns True if the collection is empty, False if it’s not.  Works with lists, sets and maps
contains(arg) returns True if arg is within the collection. Works with lists, sets and maps
add(arg) add arg to the collection. This function returns true if arg was added — in the case of a list,  arg will always be added. In the case of a set, arg will be added and return true the first time, but if the same arg is added the second time, it will return False. This member function is not found on maps
remove(arg) returns True if arg was removed from the collection, returns False is the collection is unmodified
iterator() returns an iterator over the elements of the object. This was inherited from the Iterable interface. Works with lists, sets and maps

Traversing collections

The Collections class inherits from the Iterable interface. That means all Collections classes is also an Iterable object. What that means is, we can get an iterator object from a Collections class. An iterator lets us step through the elements of an object. In each step, the value of the element is exposed to us, we can use in whatever way we want e.g. assign it to a variable, transform it or store it somewhere else, etc.

Sample code below shows how to create an immutable list of Strings and walk through each of its elements. You’ve probably done quite a lot of these when you wer coding in Java

val basket = listOf("apple", "banana", "orange")
var iter = basket.iterator()
while (iter.hasNext()) {
  println(iter.next())
}

for (i in basket) {
  println(i)
}

The sample code below is another way of traversing the same list of Strings, but this example uses the forEach function. This is a lot shorter, and is the preferred way, some people would even say, idiomatic way, of working with Kotlin collections.

fruits.forEach { println(it) }