Collections are groups of a variable number of items (possibly zero) that are significant to the problem being solved and are commonly operated on. This guide explains and compares collection concepts and operations in Java and Kotlin. It will help you migrate from Java to Kotlin and write your code in the authentically Kotlin way.
The first part of this guide contains a quick glossary of operations on the same collections in Java and Kotlin. It is divided into operations that are the same and operations that exist only in Kotlin. The second part of the guide, starting from Mutability, explains some of the differences by looking at specific cases.
For an introduction to collections, see the Collections overview or watch this video by Sebastian Aigner, Kotlin Developer Advocate.
All of the examples below use Java and Kotlin standard library APIs only.
{style="note"}
In Kotlin, there are many operations on collections that look exactly the same as their counterparts in Java.
Description | Common operations | More Kotlin alternatives |
---|---|---|
Add an element or elements | add() , addAll() |
Use the plusAssign (+= ) operator: collection += element , collection += anotherCollection . |
Check whether a collection contains an element or elements | contains() , containsAll() |
Use the in keyword to call contains() in the operator form: element in collection . |
Check whether a collection is empty | isEmpty() |
Use isNotEmpty() to check whether a collection is not empty. |
Remove under a certain condition | removeIf() |
|
Leave only selected elements | retainAll() |
|
Remove all elements from a collection | clear() |
|
Get a stream from a collection | stream() |
Kotlin has its own way to process streams: sequences and methods like map() and filter() . |
Get an iterator from a collection | iterator() |
Description | Common operations | More Kotlin alternatives |
---|---|---|
Add an element or elements | put() , putAll() , putIfAbsent() |
In Kotlin, the assignment map[key] = value behaves the same as put(key, value) . Also, you may use the plusAssign (+= ) operator: map += Pair(key, value) or map += anotherMap . |
Replace an element or elements | put() , replace() , replaceAll() |
Use the indexing operator map[key] = value instead of put() and replace() . |
Get an element | get() |
Use the indexing operator to get an element: map[index] . |
Check whether a map contains an element or elements | containsKey() , containsValue() |
Use the in keyword to call contains() in the operator form: element in map . |
Check whether a map is empty | isEmpty() |
Use isNotEmpty() to check whether a map is not empty. |
Remove an element | remove(key) , remove(key, value) |
Use the minusAssign (-= ) operator: map -= key . |
Remove all elements from a map | clear() |
|
Get a stream from a map | stream() on entries, keys, or values |
Description | Common operations | More Kotlin alternatives |
---|---|---|
Get an index of an element | indexOf() |
|
Get the last index of an element | lastIndexOf() |
|
Get an element | get() |
Use the indexing operator to get an element: list[index] . |
Take a sublist | subList() |
|
Replace an element or elements | set() , replaceAll() |
Use the indexing operator instead of set() : list[index] = value . |
Description | Java | Kotlin |
---|---|---|
Get a collection's size | size() |
count() , size |
Get flat access to nested collection elements | collectionOfCollections.forEach(flatCollection::addAll) or collectionOfCollections.stream().flatMap().collect() |
flatten() or flatMap() |
Apply the given function to every element | stream().map().collect() |
map() |
Apply the provided operation to collection elements sequentially and return the accumulated result | stream().reduce() |
reduce() , fold() |
Group elements by a classifier and count them | stream().collect(Collectors.groupingBy(classifier, counting())) |
eachCount() |
Filter by a condition | stream().filter().collect() |
filter() |
Check whether collection elements satisfy a condition | stream().noneMatch() , stream().anyMatch() , stream().allMatch() |
none() , any() , all() |
Sort elements | stream().sorted().collect() |
sorted() |
Take the first N elements | stream().limit(N).collect() |
take(N) |
Take elements with a predicate | stream().takeWhile().collect() |
takeWhile() |
Skip the first N elements | stream().skip(N).collect() |
drop(N) |
Skip elements with a predicate | stream().dropWhile().collect() |
dropWhile() |
Build maps from collection elements and certain values associated with them | stream().collect(toMap(keyMapper, valueMapper)) |
associate() |
To perform all of the operations listed above on maps, you first need to get an entrySet
of a map.
Description | Java | Kotlin |
---|---|---|
Sort a list into natural order | sort(null) |
sort() |
Sort a list into descending order | sort(comparator) |
sortDescending() |
Remove an element from a list | remove(index) , remove(element) |
removeAt(index) , remove(element) or collection -= element |
Fill all elements of a list with a certain value | Collections.fill() |
fill() |
Get unique elements from a list | stream().distinct().toList() |
distinct() |
zip()
,unzip()
– transform a collection.aggregate()
– group by a condition.takeLast()
,takeLastWhile()
,dropLast()
,dropLastWhile()
– take or drop elements by a predicate.slice()
,chunked()
,windowed()
– retrieve collection parts.- Plus (
+
) and minus (-
) operators – add or remove elements.
If you want to take a deep dive into zip()
, chunked()
, windowed()
, and some other operations, watch this video by Sebastian Aigner
about advanced collection operations in Kotlin: