Kotlin with Copilot: Merge 2 lists
Video: Kotlin with Copilot: Merge 2 lists by Taught by Celeste AI - AI Coding Coach
Kotlin: Merge Two Lists
list1 + list2is all you need. Returns a new immutable list. Other options:flatten,plus, mutable list withaddAll— pick based on whether you need mutation.
A trivial-looking puzzle that has surprisingly many "correct" answers. Copilot's default — using + — is the cleanest for the common case.
The Copilot prompt
fun main() {
val list1 = listOf(1, 2, 3)
val list2 = listOf(4, 5, 6)
// Merge two lists into one
Copilot generates:
val mergedList = list1 + list2
println(mergedList) // [1, 2, 3, 4, 5, 6]
Why + works
Kotlin defines operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> in the standard library. So list1 + list2 returns a new immutable list containing list1's elements followed by list2's.
Both inputs are unchanged — neither list is mutated. That's the standard Kotlin convention: collection operations return new collections.
Other ways to merge
// Using listOf + spread (rare, no advantage)
val merged = listOf(*list1.toTypedArray(), *list2.toTypedArray())
// Using flatten (good for many lists)
val merged = listOf(list1, list2).flatten()
// Using plus (same as +)
val merged = list1.plus(list2)
// Mutable, mutate-then-build
val merged = mutableListOf<Int>().apply {
addAll(list1)
addAll(list2)
}.toList()
// Many lists, varargs
fun <T> mergeAll(vararg lists: List<T>): List<T> = lists.flatten()
val merged = mergeAll(list1, list2, list3)
For two lists: +. For many lists: flatten. Other options exist but rarely improve on these.
In-place merge (mutable)
If list1 is a MutableList and you want to modify it:
val list1 = mutableListOf(1, 2, 3)
val list2 = listOf(4, 5, 6)
list1.addAll(list2)
println(list1) // [1, 2, 3, 4, 5, 6]
addAll(other) mutates the receiver. The receiver must be MutableList; the argument can be any Collection.
For MutableList += Iterable:
list1 += list2 // shorthand for list1.addAll(list2) when list1 is MutableList
Note: += on a var of List (immutable) reassigns to a new list:
var list = listOf(1, 2, 3)
list += listOf(4, 5)
// list now points to a new list [1, 2, 3, 4, 5]
Different mechanic — same syntax, different result. Watch the variable's type.
Removing duplicates while merging
val list1 = listOf(1, 2, 3)
val list2 = listOf(3, 4, 5)
val merged = (list1 + list2).distinct() // [1, 2, 3, 4, 5]
// Or as a set:
val mergedSet = list1.toSet() + list2.toSet() // {1, 2, 3, 4, 5}
distinct() preserves order; toSet() doesn't (unless using LinkedHashSet). For order-preserving deduplication, distinct() is what you want.
Interleaving instead of concatenating
Kotlin's standard library has zip for pair-wise alignment:
val list1 = listOf(1, 2, 3)
val list2 = listOf("a", "b", "c")
val zipped = list1.zip(list2) // [(1, "a"), (2, "b"), (3, "c")]
For interleaving (1, "a", 2, "b", 3, "c"):
val interleaved = list1.zip(list2).flatMap { listOf(it.first, it.second) }
Slightly verbose. For a generic helper:
fun <T> interleave(a: List<T>, b: List<T>): List<T> =
a.zip(b).flatMap { listOf(it.first, it.second) }
zip truncates to the shorter list. For "merge until both exhausted, padding with nulls," use zipWithNext or write explicit code.
Type compatibility
list1: List<Int> + list2: List<Int> → List<Int>.
list1: List<Number> + list2: List<Int> → List<Number> (least upper bound).
list1: List<Int> + list2: List<String> → won't compile.
Both lists must have a compatible element type. For mixed types, use Any explicitly:
val mixed: List<Any> = listOf(1, 2) + listOf("a", "b")
Possible, rarely useful.
Common mistakes
Mutating an immutable list. listOf(1, 2, 3).add(4) doesn't compile — List doesn't have add. Use mutableListOf or accept that you need a new list.
Forgetting that + returns a new list. list1 + list2 doesn't change list1. The result must be assigned: val merged = list1 + list2.
Inefficient many-list merging. (list1 + list2) + list3 + list4 creates intermediate lists. For more than a few, flatten is cleaner: listOf(list1, list2, list3, list4).flatten().
Mixing nullable elements. List<Int?> + List<Int> works; the result is List<Int?>. To filter nulls: (list1 + list2).filterNotNull().
Confusing + and +=. On val list: List<T>, += doesn't compile (immutable). On var list: List<T>, += reassigns. On val list: MutableList<T>, += mutates in place.
What's next
Episode 11: Initialize Firestore and save a Post. Set up Firebase Firestore in an Android app and persist a document.
Recap
list1 + list2 to merge — returns a new immutable List<T>. For many lists, listOf(l1, l2, l3).flatten(). For mutable receivers, addAll(other) or +=. To deduplicate, follow with .distinct(). zip for pair-wise alignment, then flatMap for interleaving.
Next episode: Firestore.