How do I convert arrays to lists and vice versa in Kotlin?

In Kotlin, you can convert arrays to lists and lists to arrays using standard library functions.

Array to List

Use toList():

val array = arrayOf("a", "b", "c")

val list: List<String> = array.toList()

println(list) // [a, b, c]

If you want a mutable list, use toMutableList():

val array = arrayOf("a", "b", "c")

val mutableList: MutableList<String> = array.toMutableList()

mutableList.add("d")

println(mutableList) // [a, b, c, d]

List to Array

Use toTypedArray():

val list = listOf("a", "b", "c")

val array: Array<String> = list.toTypedArray()

println(array.contentToString()) // [a, b, c]

Primitive Arrays

Kotlin has special primitive array types like IntArray, DoubleArray, and BooleanArray.

IntArray to List

val intArray = intArrayOf(1, 2, 3)

val list: List<Int> = intArray.toList()

println(list) // [1, 2, 3]

List<Int> to IntArray

Use toIntArray():

val list = listOf(1, 2, 3)

val intArray: IntArray = list.toIntArray()

println(intArray.contentToString()) // [1, 2, 3]

Other primitive conversions work similarly:

val doubles: List<Double> = listOf(1.1, 2.2, 3.3)
val doubleArray: DoubleArray = doubles.toDoubleArray()

val booleans: List<Boolean> = listOf(true, false)
val booleanArray: BooleanArray = booleans.toBooleanArray()

Important Note: asList()

For object arrays, you can also use asList():

val array = arrayOf("a", "b", "c")

val list = array.asList()

The difference is:

val array = arrayOf("a", "b", "c")

val copiedList = array.toList()
val backedList = array.asList()
  • toList() creates a new list copy.
  • asList() returns a list backed by the original array.

Example:

val array = arrayOf("a", "b", "c")
val list = array.asList()

array[0] = "z"

println(list) // [z, b, c]

So in most cases, use:

array.toList()
list.toTypedArray()

And for primitive types:

intArray.toList()
list.toIntArray()

How do I sort a list of values in Kotlin?

In Kotlin, you usually sort a list with sorted():

val numbers = listOf(5, 2, 8, 1)

val sortedNumbers = numbers.sorted()

println(sortedNumbers) // [1, 2, 5, 8]

sorted() returns a new sorted list and does not change the original list.

For descending order, use sortedDescending():

val numbers = listOf(5, 2, 8, 1)

val sortedDescending = numbers.sortedDescending()

println(sortedDescending) // [8, 5, 2, 1]

For objects, sort by a property with sortedBy():

data class Person(val name: String, val age: Int)

val people = listOf(
    Person("Alice", 30),
    Person("Bob", 25),
    Person("Charlie", 35)
)

val sortedByAge = people.sortedBy { it.age }

println(sortedByAge)
// [Person(name=Bob, age=25), Person(name=Alice, age=30), Person(name=Charlie, age=35)]

If you have a mutable list and want to sort it in place, use sort():

val numbers = mutableListOf(5, 2, 8, 1)

numbers.sort()

println(numbers) // [1, 2, 5, 8]

Quick summary:

  • sorted() — returns a new ascending list
  • sortedDescending() — returns a new descending list
  • sortedBy { ... } — sorts by a property
  • sort() — sorts a mutable list in place

How do I create and use lists, sets, and maps in Kotlin?

In Kotlin, the main collection types are List, Set, and Map.

Kotlin provides both read-only and mutable versions:

Collection Read-only Mutable
List List<T> MutableList<T>
Set Set<T> MutableSet<T>
Map Map<K, V> MutableMap<K, V>

Lists

A list is an ordered collection. It can contain duplicate elements.

Read-only list

val numbers = listOf(1, 2, 3, 3)

println(numbers[0])        // 1
println(numbers.size)      // 4
println(numbers.contains(2)) // true

You cannot add or remove items from a read-only List.

val names = listOf("Alice", "Bob", "Charlie")

for (name in names) {
    println(name)
}

Mutable list

val names = mutableListOf("Alice", "Bob")

names.add("Charlie")
names.remove("Alice")
names[0] = "Bobby"

println(names) // [Bobby, Charlie]

You can also create an empty mutable list:

val items = mutableListOf<String>()

items.add("Book")
items.add("Pen")

println(items) // [Book, Pen]

Sets

A set is a collection of unique elements. It does not allow duplicates.

Read-only set

val numbers = setOf(1, 2, 3, 3)

println(numbers) // [1, 2, 3]
println(2 in numbers) // true

Mutable set

val fruits = mutableSetOf("Apple", "Banana")

fruits.add("Orange")
fruits.add("Apple") // Duplicate, ignored
fruits.remove("Banana")

println(fruits) // [Apple, Orange]

Empty mutable set:

val ids = mutableSetOf<Int>()

ids.add(101)
ids.add(102)

println(ids) // [101, 102]

Maps

A map stores key-value pairs. Each key is unique.

Read-only map

val ages = mapOf(
    "Alice" to 25,
    "Bob" to 30,
    "Charlie" to 35
)

println(ages["Alice"]) // 25
println(ages["Unknown"]) // null
println(ages.containsKey("Bob")) // true
println(ages.containsValue(30)) // true

Mutable map

val scores = mutableMapOf(
    "Alice" to 90,
    "Bob" to 85
)

scores["Charlie"] = 95
scores["Alice"] = 100
scores.remove("Bob")

println(scores) // {Alice=100, Charlie=95}

Empty mutable map:

val phoneBook = mutableMapOf<String, String>()

phoneBook["Alice"] = "123-456"
phoneBook["Bob"] = "987-654"

println(phoneBook["Alice"]) // 123-456

Common operations

Iterating over a list or set

val colors = listOf("Red", "Green", "Blue")

for (color in colors) {
    println(color)
}

Iterating over a map

val ages = mapOf(
    "Alice" to 25,
    "Bob" to 30
)

for ((name, age) in ages) {
    println("$name is $age years old")
}

Filtering

val numbers = listOf(1, 2, 3, 4, 5, 6)

val evenNumbers = numbers.filter { it % 2 == 0 }

println(evenNumbers) // [2, 4, 6]

Mapping values

val names = listOf("alice", "bob", "charlie")

val uppercaseNames = names.map { it.uppercase() }

println(uppercaseNames) // [ALICE, BOB, CHARLIE]

Sorting

val numbers = listOf(5, 2, 8, 1)

val sorted = numbers.sorted()

println(sorted) // [1, 2, 5, 8]

Checking contents

val names = listOf("Alice", "Bob")

println("Alice" in names) // true
println("Charlie" !in names) // true

Choosing between them

Use a List when:

  • Order matters
  • Duplicates are allowed
  • You access elements by index
val tasks = listOf("Write", "Test", "Deploy")

Use a Set when:

  • Values must be unique
  • You mainly check whether something exists
val uniqueTags = setOf("kotlin", "backend", "api")

Use a Map when:

  • You need key-value lookup
  • Each key maps to one value
val userRoles = mapOf(
    1 to "Admin",
    2 to "Editor",
    3 to "Viewer"
)

Quick summary

val readOnlyList = listOf("A", "B", "C")
val mutableList = mutableListOf("A", "B")
mutableList.add("C")

val readOnlySet = setOf("A", "B", "A") // [A, B]
val mutableSet = mutableSetOf("A", "B")
mutableSet.add("C")

val readOnlyMap = mapOf("Alice" to 25, "Bob" to 30)
val mutableMap = mutableMapOf("Alice" to 25)
mutableMap["Bob"] = 30

In short:

  • listOf() creates a read-only list
  • mutableListOf() creates a mutable list
  • setOf() creates a read-only set
  • mutableSetOf() creates a mutable set
  • mapOf() creates a read-only map
  • mutableMapOf() creates a mutable map

How do I use List.of, Set.of, and Map.of factory methods?

The List.of, Set.of, and Map.of factory methods were introduced in Java 9 to create immutable collections in a simpler and more concise way. These methods directly create unmodifiable instances of List, Set, or Map.

Usage of List.of

The List.of method is used to create an unmodifiable List containing the provided elements. The key characteristics are:

  • The list is immutable, meaning you cannot modify its contents (e.g., add, remove, replace elements).
  • If you attempt to modify the list, a java.lang.UnsupportedOperationException will be thrown.

Key Points:

  1. It is null-safety aware, meaning null is not allowed as an element.
  2. The created list maintains the insertion order.

Example

List<String> names = List.of("Rosa", "John", "Mary", "Alice");
System.out.println(names); // Output: [Rosa, John, Mary, Alice]

names.add("Bob"); // Throws java.lang.UnsupportedOperationException

Note: Attempting to pass a null element will result in NullPointerException.


Usage of Set.of

The Set.of method creates an immutable Set containing the given elements. The key characteristics are:

  • The set is unmodifiable, so you cannot add or remove elements after creation.
  • It does not allow duplicate elements.
  • It does not allow null elements.

Key Points:

  1. A java.lang.IllegalArgumentException is thrown if duplicate elements are provided during creation.
  2. Since a Set does not guarantee order, the order of elements in the resulting set is not predictable.

Example

Set<String> items = Set.of("apple", "banana", "orange");
System.out.println(items); // Output: [apple, banana, orange] (order may vary)

items.add("kiwi"); // Throws java.lang.UnsupportedOperationException

Note: If duplicate elements are passed, an exception will be thrown:

Set.of("apple", "banana", "apple"); // Throws IllegalArgumentException

Usage of Map.of

The Map.of method creates an immutable Map with key-value pairs. The characteristics are:

  • The created map is unmodifiable.
  • Both null keys and null values are not allowed.
  • Duplicate keys are not allowed, and attempting to use duplicate keys will throw IllegalArgumentException.

Example

Map<String, Integer> map = Map.of("John", 25, "Mary", 30, "Alice", 27, "Rosa", 22);

System.out.println(map); 
// Output (order may vary): {John=25, Mary=30, Alice=27, Rosa=22}

map.put("Bob", 31); // Throws java.lang.UnsupportedOperationException

Note: Avoid duplicate keys. For example:

Map.of("Key1", 1, "Key2", 2, "Key1", 3); // Throws IllegalArgumentException

Advantages of List.of, Set.of, and Map.of

  1. Immutable collections help ensure thread safety without additional synchronization.
  2. Improved code conciseness compared to using Collections.unmodifiableList, Collections.unmodifiableSet, or Collections.unmodifiableMap.
  3. Simplified initialization with a clean and readable API.

For larger maps (more than 10 entries), use Map.ofEntries for better clarity:

Map<String, Integer> largeMap = Map.ofEntries(
    Map.entry("Alice", 27),
    Map.entry("John", 25),
    Map.entry("Mary", 30),
    Map.entry("Rosa", 22)
);

How do I use the List.sort() method?

The List.sort() method was introduced in Java 8. This method sorts the elements of the list on the basis of the given Comparator. If no comparator is provided, it will use the natural ordering of the elements (only if the elements are Comparable).

Let’s take a look at an example where we sort a list of integers in ascending order:

package org.kodejava.util;

import java.util.ArrayList;
import java.util.List;

public class ListSortExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(3);
        numbers.add(1);
        numbers.add(4);
        numbers.add(1);
        numbers.add(5);

        // Use sort() to sort the numbers in ascending order
        numbers.sort(null);

        System.out.println(numbers); 
    }
}

Outputs:

[1, 1, 3, 4, 5]

You can also pass a Comparator to List.sort(). Here’s an example where we sort a list of strings by their length:

package org.kodejava.util;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class ListSortOtherExample {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>();
        words.add("rat");
        words.add("elephant");
        words.add("cat");
        words.add("mouse");

        // Comparator for comparing string lengths
        Comparator<String> lengthComparator = (s1, s2) -> s1.length() - s2.length();

        // Use sort() to sort the words by their length
        words.sort(lengthComparator);

        System.out.println(words);
    }
}

Outputs:

[rat, cat, mouse, elephant]

In this case, the Comparator is a lambda expression that computes the difference in length between two strings. The List.sort() method uses this Comparator to determine the ordering of the strings in the list.