JVM中性能更好的ArrayList<Int>

前言

众所周知,kotlin中有ArrayList<Int>,Array<Int>,IntArray,可他们都有什么区别呢?为什么要有这么多大致相同的类型?

正文

我们先看一下他们相对于jvm中的类型

ArrayList<Int> = ArrayList<Integer>

Array<Int> = Integer[]

IntArray = int[]

可以看出来前面两种都用到了int的包装类型Integer,而IntArray是用的基础数据类型int,在下面这篇文章中看到,由于jvm的自动装箱和拆箱导致包装类型性能更差(时间和空间上).[Kotlin的基本数值类型问题:是对象?还是基本数据类型?]

但是ArrayList<Int>是有可变的数量上限的(扩容机制),而IntArray并没有,如果我们想要一个可以扩容的IntArray,而且也使用基础数据类型(性能更好)时,怎么办呢?我们可以仿照ArrayList<Int>写一个基本数据类型的,如下代码:

ps:项目已开源: ltttttttttttt/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的话,只需要copy一份将Int改成Double就可以了

end

扫描二维码关注公众号,回复: 15072885 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_33505109/article/details/125068764