Kotlin Generics, Collections, and Operators – Chapter 6
This article explains Kotlin's generic type system, collection interfaces, variance with in/out keywords, collection initialization methods, and the extensive set of operators, providing code examples and implementation details to help developers master Kotlin's core language features.
The Kotlin tutorial series continues with the final chapter, covering generics, collection interfaces, variance, initialization, and operators.
6.1 Kotlin Collection Interfaces
The diagram shows the inheritance hierarchy of Kotlin collection interfaces; interfaces marked with out are read‑only (e.g., only get(), size), while those without out or prefixed with Mutable are mutable, mirroring Java collections.
6.2 in and out
The out keyword makes a generic type covariant, allowing a List<C> to be assigned to a List<A>. The opposite, in, makes a type contravariant, meaning it can be used only as a method parameter.
open class A
open class B : A()
open class C : B()
val mutableList: MutableList<B> = mutableListOf(B(), B(), C())
val list: List<A> = mutableListUsing in in a generic declaration restricts the type to input positions only.
open class A
open class B : A()
open class C : B()
class TypeArray<in A> {
// 'in' marks A as a parameter type only
fun getValue(a: A): Int? { return a?.hashCode() }
// Illegal: returning A because it is 'in'
fun getA(a: A): A? { return a }
}6.3 Collection Initialization
Kotlin prefers factory functions over constructors for creating collections. Examples include mutableListOf(), listOf(), and setOf(). These functions return underlying Java collection implementations such as java.util.ArrayList or java.util.HashSet.
val mutableList = mutableListOf(0, 1, 2, 3)
var list = listOf(0, 1, 2)
val ss = setOf(1, 2, 4)The returned objects are Java collections like ArrayList, LinkedHashMap, HashMap, LinkedHashSet, HashSet, SortedSet, and TreeSet. Some Java types such as LinkedList are not provided via these helpers.
6.4 Operators
Kotlin operators are regular methods (often extension functions) that act on data. They are similar to RxJava operators, and the article lists common ones with brief descriptions, accompanied by illustrative images.
6.5 Operator Implementation Principle
The forEach operator is shown as a simple example: it is an extension function on Iterable that iterates over each element and invokes a lambda.
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}Custom operators can be created similarly; the article provides a convert extension that transforms a list from type A to B using a supplied lambda.
inline fun <T, E> Iterable<T>.convert(action: (T) -> E): MutableList<E> {
val list: MutableList<E> = mutableListOf()
for (element in this) list.add(action(element))
return list
}
val list: List<String> = listOf("hello", "world")
list.convert { it.hashCode() }.forEach { print("$it") }6.6 Common Operators
The article categorizes operators into index operations (e.g., contains, elementAt), predicate checks ( any, all, none, count, reduce), filtering ( filter, filterNot, filterNotNull, take), transformation ( map, mapIndexed, mapNotNull, flatMap, groupBy), and sorting ( reversed, sorted, sortedBy, sortedDescending).
Additional reading links and images conclude the article.
Hujiang Technology
We focus on the real-world challenges developers face, delivering authentic, practical content and a direct platform for technical networking among developers.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
