返回

Kotlin 集和 2:ArrayList 源码分析

Android

在讨论 Kotlin 中的集合类型时,ArrayList 是一种常见的可变数组列表。它提供了一种灵活的方式存储元素,并支持高效的随机访问。本文将深入探讨 ArrayList 的源代码实现,重点在于其内部机制、性能考量以及线程安全特性。

ArrayList 如何管理其元素

内部数据结构

ArrayList 在 Kotlin 中的实现是基于 Java 平台上的 java.util.ArrayList 类。它使用一个动态大小的数组来存储元素,并通过重载操作符和提供多个方法来进行添加、删除和查找等操作。

在 Kotlin 的源代码中,可以通过查看 kotlin.collections.ArrayList 来了解其内部是如何定义的。例如:

// ArrayList 内部构造器会调用 Java 的 ArrayList 构造函数来初始化一个空数组。
class ArrayList<E> : AbstractMutableList<E>(), RandomAccess, MutableList<E>, Collection<E> {
    override val size: Int get() = modCount

    private var array = emptyArray<Any?>()
}

这里的 array 是用来存储元素的实际数组。

动态调整容量

随着元素的添加,当原始数组无法容纳更多数据时,会动态增加其容量。这个过程在源码中通过扩展当前数组并复制内容实现:

private fun ensureCapacity(size: Int) {
    if (this.array.size < size) {
        this.array = growArray(this.array, size)
    }
}

当需要的空间超过现有数组大小时,会调用 growArray 方法来创建一个新的、更大的数组。

处理不同操作

添加元素

添加一个新元素到列表中是通过将该元素追加至数组末尾实现的。如果当前数组已满,则先扩展其容量:

fun add(element: E): Boolean {
    ensureCapacity(size + 1)
    array[size] = element
    size++
    return true
}

删除元素

删除操作涉及到移动后续所有元素,以覆盖被移除的元素位置。这可能导致性能上的下降。

operator fun remove(element: E): Boolean {
    val index = indexOf(element)
    if (index == -1) return false
    removeAt(index)
    return true
}

private fun removeAt(index: Int): E? {
    ensureCapacity(size)
    val element = array[index] as E?
    System.arraycopy(array, index + 1, array, index, size - index - 1)
    size--
    return element
}

确保线程安全性

尽管 ArrayList 自身不是线程安全的,但可以通过使用同步包装器来使其适应多线程环境。Kotlin 提供了 synchronizedList 函数,用于将列表转换为线程安全版本:

val threadSafeList = Collections.synchronizedList(ArrayList<String>())

最佳实践

为了最佳地利用 ArrayList 的特性,以下几点是开发者需要注意的:

  • 尽量减少频繁的数组扩容操作。
  • 对于读多写少的应用场景,考虑使用 CopyOnWriteArrayList 代替基本的 ArrayList

通过理解源码,可以更好地把握数据结构内部的工作机制,并在实际开发中优化性能和维护代码质量。