How to use collections in Kotlin development

  • 2021-08-31 09:07:04
  • OfStack

About Kotlin development

Developing Android and App using Kotlin is becoming more and more popular among Java engineers. If you miss Kotlin for some reason, we strongly recommend that you read this article.

For those developers who are at the forefront of technology and like Kotlin, this article is closely related to them. So, let's look at how to use collections in Kotlin.

Collections in Kotlin are a framework based on Java collections. This article focuses on several features in the kotlin. collections package.

Data processing

Kotlin has an extension function feature that enables the Kotlin standard library (stdlib) to support the methods of the classes in JDK. For example, if you open the open_Collection. kt file in the Kotlin standard library, you can find a method very similar to the following:


/**
* Returns a list containing only elements matching the given [predicate].
*/
public inline fun <T> Iterable<T>.filter(predicate: (T) -> Boolean): List<T> {
 return filterTo(ArrayList<T>(), predicate)
}

So, the code you write might look like this:


val originalList = listOf(1, 2, 3, 4, 5, 6)
assertEquals(listOf(2, 4, 6), originalList.filter { it % 2 == 0 })
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.firstOrNull { it > 4 }
assertEquals(result, 5)
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.getOrElse(12) { 12 }
assertEquals(result, 12)
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.dropWhile { it < 5 }
assertEquals(result, listOf(5, 6, 7, 8, 9, 10))
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList
    .dropWhile { it < 5 }
    .find { it < 7 }
assertEquals(result, 5)

You should note that filter and dropWhile, like other operators 1, return a new instance. This means that originalList will not change.

To better understand what is happening at the bottom of the code, let's open the source code and look at the listOf () method:


/** Returns a new read-only list of given elements. The returned list is serializable (JVM). */
public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

Because Stream API of RxJava and Java 8 contain similar methods, the above code is very similar to RxJava and Stream API. But because Android engineers can't use Stream API, they use more RxJava data processing methods to solve this problem. However, this operation is not entirely correct because RxJava is an event processing library, not data processing. So you can now use Kotlin to solve this problem without worrying about these problems.

Immutable set

If you are unfamiliar with immutable objects (immutable object), we suggest that you read this document first and then read this one again.

Kotlin distinguishes between variable objects (ES80object) and immutable objects (lists, sets, maps, etc.) in a different way from other programming languages. Accurately distinguishing these two types of objects when using the Kotlin collection is useful to avoid unnecessary errors and bug.

Kotlin allows the creation of a collection instance of Kotlin in a similar way to Java.


val list = ArrayList<String>()

This is the simplest and neatest way. The following method is the best way to write it:


val list: kotlin.collections.List<String> = java.util.ArrayList()

I created an kotlin. collections. List reference, and we also created an immutable collection. If you don't believe it very much, then we can look at the source code 1:


public interface List<out E> : Collection<E> {
 // Query Operations
 override val size: Int
 override fun isEmpty(): Boolean
 override fun contains(element: @UnsafeVariance E): Boolean
 override fun iterator(): Iterator<E>

 // Bulk Operations
 override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean

 // Positional Access Operations
 /**
 * Returns the element at the specified index in the list.
 */
 public operator fun get(index: Int): E

 // Search Operations
 /**
 * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified
 * element is not contained in the list.
 */
 public fun indexOf(element: @UnsafeVariance E): Int

 /**
 * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified
 * element is not contained in the list.
 */
 public fun lastIndexOf(element: @UnsafeVariance E): Int

 // List Iterators
 /**
 * Returns a list iterator over the elements in this list (in proper sequence).
 */
 public fun listIterator(): ListIterator<E>

 /**
 * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index].
 */
 public fun listIterator(index: Int): ListIterator<E>

 // View
 /**
 * Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive).
 * The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa.
 */
 public fun subList(fromIndex: Int, toIndex: Int): List<E>
}

You see that there is no add () method, no remove () method in the source code, and there are no other ways to change this collection. In this example, the instance itself is java. util. ArrayList. Let's explain why with an example:


val list: kotlin.collections.MutableList<String> = java.util.ArrayList()
list.add("string")

You'd better look at this example in the local source code:


public interface MutableList<E> : List<E>, MutableCollection<E> {
 // Modification Operations
 override fun add(element: E): Boolean
 override fun remove(element: E): Boolean

 // Bulk Modification Operations
 override fun addAll(elements: Collection<E>): Boolean

 /**
 * Inserts all of the elements in the specified collection [elements] into this list at the specified [index].
 *
 * @return `true` if the list was changed as the result of the operation.
 */
 public fun addAll(index: Int, elements: Collection<E>): Boolean
 override fun removeAll(elements: Collection<E>): Boolean
 override fun retainAll(elements: Collection<E>): Boolean
 override fun clear(): Unit

 // Positional Access Operations
 /**
 * Replaces the element at the specified position in this list with the specified element.
 *
 * @return the element previously at the specified position.
 */
 public operator fun set(index: Int, element: E): E

 /**
 * Inserts an element into the list at the specified [index].
 */
 public fun add(index: Int, element: E): Unit

 /**
 * Removes an element at the specified [index] from the list.
 *
 * @return the element that has been removed.
 */
 public fun removeAt(index: Int): E

 // List Iterators
 override fun listIterator(): MutableListIterator<E>
 override fun listIterator(index: Int): MutableListIterator<E>

 // View
 override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>
}

How to understand: Is ArrayList of Java like List1 of Kotlin?


val list: kotlin.collections.List<String> = java.util.ArrayList()

In fact, there is nothing strange here. The collection of Kotlin inherits the interface of Java to List. We can see from the file kotlin. collections. Collection. kt:


@file:kotlin.jvm.JvmMultifileClass
@file:kotlin.jvm.JvmName("CollectionsKt")
package kotlin.collections
import kotlin.comparisons.compareValues

As mentioned earlier, this file contains all the collection extension methods. We can see that we can use almost all the methods in the Java CollectionsKT class in Kotlin. Of course, we also need to import java.util.*.

Let's look at how we call the Kotlin collection in the Java code:


val originalList = listOf(1, 2, 3, 4, 5, 6)
assertEquals(listOf(2, 4, 6), originalList.filter { it % 2 == 0 })
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.firstOrNull { it > 4 }
assertEquals(result, 5)
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.getOrElse(12) { 12 }
assertEquals(result, 12)
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList.dropWhile { it < 5 }
assertEquals(result, listOf(5, 6, 7, 8, 9, 10))
val originalList = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val result = originalList
    .dropWhile { it < 5 }
    .find { it < 7 }
assertEquals(result, 5)
0

You can now clearly see how the Kotlin collection uses Java's List. All extension functions can be accessed as static methods.

Summarize

Android development language Kotlin is a very interesting language. It can help us write more concise and secure code. Except for the first time, Kotlin is compatible with Java.


Related articles: