kotlin-collections-api
Overview of Kotlin Collections API
1. Overview
2. Collection vs. Mutable Collection
First, let’s take a look at different types of collections in Kotlin. We will see how to initialize basic types of collections.
The Collection interface supports read-only methods while MutableCollection support read/write methods.
2.1. List
We can create a simple read-only List using method listOf() and read-write MutableList using mutableListOf():
val theList = listOf("one", "two", "three")
val theMutableList = mutableListOf("one", "two", "three")
3. Useful Operators
Kotlin’s Collections API is much richer than the one we can find in Java – it comes with a set of overloaded operators.
3.1. The “in” Operator
@Test
fun whenSearchForExistingItem_thenFound () {
val theList = listOf("one", "two", "three")
assertTrue("two" in theList)
}
3.2. The “+” Operator
[[the—operator]]We can an element or entire collection to another using “+” operator:
@Test
fun whenJoinTwoCollections_thenSuccess () {
val firstList = listOf("one", "two", "three")
val secondList = listOf("four", "five", "six")
val resultList = firstList + secondList
assertEquals(6, resultList.size)
assertTrue(resultList.contains("two"))
assertTrue(resultList.contains("five"))
}
3.3. The “-“ Operator
@Test
fun whenExcludeItems_thenRemoved () {
val firstList = listOf("one", "two", "three")
val secondList = listOf("one", "three")
val resultList = firstList - secondList
assertEquals(1, resultList.size)
assertTrue(resultList.contains("two"))
}
4. Other Methods
Finally, we will explore some common methods for collection. In Java, if we wanted to leverage advanced methods, we would need to use Stream API.
In Kotlin, we can find similar methods available in the Collections API.
We can obtain a sublist from a given List:
@Test
fun whenSliceCollection_thenSuccess () {
val theList = listOf("one", "two", "three")
val resultList = theList.slice(1..2)
assertEquals(2, resultList.size)
assertTrue(resultList.contains("two"))
}
We can easily remove all nulls from a List:
@Test
fun whenFilterNullValues_thenSuccess () {
val theList = listOf("one", null, "two", null, "three")
val resultList = theList.filterNotNull()
assertEquals(3, resultList.size)
}
We can filter collection items easily using filter(), which works similarly to the filter() method from Java Stream API:
@Test
fun whenFilterNonPositiveValues_thenSuccess () {
val theList = listOf(1, 2, -3, -4, 5, -6)
val resultList = theList.filter{ it > 0}
assertEquals(3, resultList.size)
assertTrue(resultList.contains(1))
assertFalse(resultList.contains(-4))
}
We can drop first N items:
@Test
fun whenDropFirstItems_thenRemoved () {
val theList = listOf("one", "two", "three", "four")
val resultList = theList.drop(2)
assertEquals(2, resultList.size)
assertFalse(resultList.contains("one"))
assertFalse(resultList.contains("two"))
}
We can drop items first few items if they satisfy the given condition:
@Test
fun whenDropFirstItemsBasedOnCondition_thenRemoved () {
val theList = listOf("one", "two", "three", "four")
val resultList = theList.dropWhile{ it.length < 4 }
assertEquals(2, resultList.size)
assertFalse(resultList.contains("one"))
assertFalse(resultList.contains("two"))
}
We can group elements:
@Test
fun whenGroupItems_thenSuccess () {
val theList = listOf(1, 2, 3, 4, 5, 6)
val resultMap = theList.groupBy{ it % 3}
assertEquals(3, resultMap.size)
assertTrue(resultMap[1]!!.contains(1))
assertTrue(resultMap[2]!!.contains(5))
}
We can map all elements using the provided function:
@Test
fun whenApplyFunctionToAllItems_thenSuccess () {
val theList = listOf(1, 2, 3, 4, 5, 6)
val resultList = theList.map{ it * it }
assertEquals(4, resultList[1])
assertEquals(9, resultList[2])
}
We can use flatmap() to flatten nested collections. Here, we are converting Strings to List<String> and avoiding ending up with List<List<String>>:
@Test
fun whenApplyMultiOutputFunctionToAllItems_thenSuccess () {
val theList = listOf("John", "Tom")
val resultList = theList.flatMap{ it.toLowerCase().toList() }
assertEquals(7, resultList.size)
}
We can perform fold/reduce operation:
@Test
fun whenApplyFunctionToAllItemsWithStartingValue_thenSuccess () {
val theList = listOf(1, 2, 3, 4, 5, 6)
val finalResult = theList.fold(0, {acc, i -> acc + (i * i)})
assertEquals(91, finalResult)
}
5. Conclusion
And, as always, the full source code can be found over on GitHub.