Лучшая производительность ArrayList<Int> в JVM

предисловие

Как мы все знаем, в kotlin есть ArrayList<Int>, Array<Int>, IntArray, но в чем между ними разница, почему так много примерно одинаковых типов?

текст

Давайте сначала посмотрим на их типы относительно jvm

ArrayList<Целое> = ArrayList<Целое>

Массив<Целое> = Целое[]

IntArray = интервал []

Видно, что первые два типа используют тип упаковки int Integer, в то время как IntArray использует базовый тип данных int.Как вы можете видеть в следующей статье, производительность типа упаковки хуже из-за автоматической упаковки и распаковки jvm. (Во времени и пространстве). [Основная проблема числового типа Котлина: это объект? Или базовый тип данных?]

Но у ArrayList<Int> есть переменный верхний предел (механизм расширения), а у IntArray нет. Что нам делать, если мы хотим, чтобы IntArray можно было расширять, а также использовать базовые типы данных (более высокая производительность)? Мы можем написать базовые данные введите как ArrayList<Int> следующим образом:

ps: проект с открытым исходным кодом:  lttttttttttt/DataStructure: (обычно используемые пользовательские структуры данных) (github.com)

package com.lt.androidkj.utils.collection

/**
 * creator: lt  2021/11/10  [email protected]
 * effect : 性能更好的ArrayList<Int>,线程不安全
 * warning:[initSize]初始化容量
 */
class IntArrayList(initSize: Int = 10) : RandomAccess {
    constructor(intArray: IntArray) : this(intArray.size) {
        data = intArray.copyOf()
        size = data.size
    }

    constructor(intArrayList: IntArrayList) : this(intArrayList.data.copyOf(intArrayList.size))

    constructor(list: Collection<Int>) : this(list.size) {
        list.forEach(::add)
    }

    //内部数据
    private var data: IntArray = IntArray(initSize) { 0 }

    /**
     * 获取内部的总数量
     */
    var size: Int = 0
        private set

    /**
     * 获取数据
     */
    operator fun get(index: Int): Int {
        if (index >= size)
            throw IndexOutOfBoundsException("size = $size ,the index = $index")
        return data[index]
    }

    /**
     * 获取数据,如果索引越界,就返回else的返回值
     */
    inline fun getOrElse(index: Int, defaultValue: () -> Int): Int {
        if (index !in 0 until size)
            return defaultValue()
        return get(index)
    }

    /**
     * 获取数据,如果索引越界,就返回null
     */
    fun getOrNull(index: Int): Int? {
        if (index !in 0 until size)
            return null
        return get(index)
    }

    /**
     * 添加数据
     * 扩容机制:容量翻倍
     */
    fun add(element: Int) {
        if (size == data.size)
            data = data.copyOf(data.size * 2)
        data[size] = element
        size++
    }

    /**
     * 根据数据移除
     */
    fun removeElement(element: Int) {
        val indexOf = indexOf(element)
        if (indexOf >= 0) {
            removeAtIndex(indexOf)
        }
    }

    /**
     * 根据索引移除
     */
    fun removeAtIndex(index: Int) {
        if (index >= size)
            throw IndexOutOfBoundsException("size = $size ,the index = $index")
        val numMoved = size - index - 1
        if (numMoved > 0)
            System.arraycopy(data, index + 1, data, index, numMoved)
        size--
    }

    /**
     * 移除第一个位置
     */
    fun removeFirst() = removeAtIndex(0)

    /**
     * 移除最后一个位置
     */
    fun removeLast() = removeAtIndex(size - 1)

    /**
     * 设置某个索引的数据
     */
    operator fun set(index: Int, element: Int): Int {
        if (index >= size)
            throw IndexOutOfBoundsException("size = $size ,the index = $index")
        val oldElement = get(index)
        data[index] = element
        return oldElement
    }

    /**
     * 如果[index]没有超过size就设置,否则丢弃该次修改
     */
    fun setOrDiscard(index: Int, element: Int) {
        if (index >= size || index < 0) return
        set(index, element)
    }

    /**
     * 获取内部是否没有数据
     */
    fun isEmpty(): Boolean = size == 0

    /**
     * 获取对应数据的索引,如果没有则返回-1
     */
    fun indexOf(element: Int): Int {
        forEachIndexed { index, datum ->
            if (element == datum)
                return index
        }
        return -1
    }

    /**
     * 从后往前获取对应数据的索引,如果没有则返回-1
     */
    fun lastIndexOf(element: Int): Int {
        forEachReversedIndexed { index, datum ->
            if (element == datum)
                return index
        }
        return -1
    }

    /**
     * 获取是否存在对应数据
     */
    operator fun contains(element: Int): Boolean = indexOf(element) >= 0

    /**
     * 获取迭代器
     */
    operator fun iterator(): MutableIterator<Int> = object : MutableIterator<Int> {
        private var index = 0
        override fun hasNext(): Boolean = size > index
        override fun next(): Int = get(index++)
        override fun remove() = removeAtIndex(--index)
    }

    /**
     * 遍历的方法
     * ps:使用forEach系列比for性能好(因为迭代器的next()返回的是对象)
     */
    inline fun forEach(action: (element: Int) -> Unit) {
        forEachIndexed { _, element -> action(element) }
    }

    inline fun forEachIndexed(action: (index: Int, element: Int) -> Unit) {
        var index = 0
        while (index < size) {
            action(index, get(index))
            index++
        }
    }

    /**
     * 倒序遍历
     */
    inline fun forEachReversedIndexed(action: (index: Int, element: Int) -> Unit) {
        var index = size - 1
        while (index >= 0) {
            action(index, get(index))
            index--
        }
    }

    /**
     * 获取一段IntArrayList
     */
    fun subList(fromIndex: Int, toIndex: Int): IntArrayList {
        if (toIndex > size)
            throw IndexOutOfBoundsException("size = $size ,the toIndex = $toIndex")
        return IntArrayList(data.copyOfRange(fromIndex, toIndex))
    }

    /**
     * 安全的subList,索引超限部分不会返回内容
     */
    fun subListWithSafe(fromIndex: Int, toIndex: Int): IntArrayList =
        IntArrayList(data.copyOfRange(maxOf(0, fromIndex), minOf(size, toIndex)))

    /**
     * 批量添加数据
     */
    fun addAll(elements: Collection<Int>) {
        elements.forEach(::add)
    }

    fun addAll(elements: IntArrayList) {
        addAll(elements.data.copyOf(elements.size))
    }

    fun addAll(elements: IntArray) {
        elements.forEach(::add)
    }

    fun addAllNotNull(elements: Collection<Int?>?) {
        elements?.forEach {
            if (it != null)
                add(it)
        }
    }

    /**
     * 批量移除数据
     */
    fun removeAll(elements: Collection<Int>) {
        elements.forEach(::removeElement)
    }

    fun removeAll(elements: IntArrayList) {
        removeAll(elements.data.copyOf(elements.size))
    }

    fun removeAll(elements: IntArray) {
        elements.forEach(::removeElement)
    }

    /**
     * 清空数据
     */
    fun clear() {
        size = 0
    }

    /**
     * 转换数据结构
     */
    fun toIntArray() = data.copyOf(size)

    fun toMutableList() = toIntArray().toMutableList()

    override fun toString(): String {
        return "[" + data.copyOf(size).joinToString(",") + "]"
    }
}

fun intArrayListOf(vararg elements: Int): IntArrayList = IntArrayList(elements)

Его производительность лучше, базовый тип данных используется внутри, и он поддерживает автоматическое расширение.Метод использования в основном такой же, как у ArrayList.

Если вы хотите установить Double, вам нужно только сделать копию и изменить Int на Double

конец

おすすめ

転載: blog.csdn.net/qq_33505109/article/details/125068764