手写一个ArrayList

1. 手写一个MyArrayList

ArrayList 类是一个可以动态修改的数组,与普通数组的区别就是它是支持动态扩容,即没有固定大小的限制,我们可以添加或删除元素。

ArrayList 本质是数组,故具有查询快,增删慢的特点

  • add():新增时需要考虑扩容的因素。这个是区别数组的核心方法
  • get(): 非常好地体现出下标查找的优势,故查询快
  • remove():体现出数组的缺点,删除一个元素,后面的元素需整体前移,故删除慢
优点:
  • 1、根据下标遍历元素效率较高。
  • 2、根据下标访问元素效率较高。
  • 3、在数组的基础上封装了对元素操作的方法。
  • 4、可以自动扩容。
缺点:
  • 1、插入和删除的效率比较低。
  • 2、根据内容查找元素的效率较低。
    扩容规则:每次扩容现有容量的50%。

2. 自定义 MyArrayList

2.1 IMyList.java

主要实现IMyList定义的函数,例如add、get、remove、contains

IMyList.java

package com.sufadi.study.arrayList

interface IMyList {
    fun size(): Int

    fun isEmpty(): Any

    // 是否存在
    fun contains(objects: Any): Boolean

    fun clear()

    fun add(objects: Any): Boolean

    fun remove(index: Int): Boolean

    fun get(index: Int): Any?

}

2.1 MyArrayList.java

add():新增时需要考虑扩容的因素。这个是区别数组的核心方法
get(): 非常好地体现出下标查找的优势,故查询快
remove():体现出数组的缺点,删除一个元素,后面的元素需整体前移,故删除慢

package com.sufadi.study.arrayList

import java.lang.Exception

/**
 * 学习文章来源
 * https://blog.csdn.net/weixin_40834464/article/details/82750466
 */
class MyArrayList @JvmOverloads constructor(private var capacitySize: Int = DEFAULT_CAPACITY) : IMyList {

    // JDK 源码规定的长度
    companion object {
        internal val DEFAULT_CAPACITY = 10
    }

    var size: Int = 0
    private  var elementDatas: Array<Any?>

    init {
        elementDatas = arrayOfNulls(capacitySize)
    }

    override fun add(objects: Any): Boolean {
        // 数组扩容函数:超出就扩容1倍
        ensureCapacity()
        elementDatas[size] = objects
        size++
        return false
    }

    override fun contains(objects: Any) : Boolean{
        for (data in elementDatas) {
            if (data == objects) {
                return true
            }
        }
        return false
    }

    override fun get(index: Int): Any? {
        // 对索引下标进行合法性检查
        rangeCheck(index)
        return elementDatas[index]
    }

    override fun remove(index: Int): Boolean {
        // 对索引下标进行合法性检查
        rangeCheck(index)

        val offsetSize = size - index - 1
        /**
         * 思路: 删除1个,整体前移1位,最后一位置空
         *
         * src:要复制的数组(源数组):elementDatas
         * srcPos:复制源数组的起始位置:index + 1
         * dest:目标数组:elementDatas
         * destPos:目标数组的下标位置:被删除的位置为起点
         * length:要复制的长度:offsetSize
         */
        println("   remove index=$index, 数组整体移动1位,将index(${index+1} 到${index+1+offsetSize})区域整体放到(${index} 到 ${index+offsetSize})区域")
        System.arraycopy(elementDatas, index + 1, elementDatas, index, offsetSize)
        elementDatas[size - 1] = null
        return true
    }

    override fun isEmpty(): Any {
        return size == 0
    }

    override fun clear() {
        elementDatas = arrayOf(capacitySize)
        size = 0
    }

    override fun size(): Int {
        return size
    }

    /**
     * 数组扩容函数:超出就扩容1倍,数组复制实现
     */
    private fun ensureCapacity() {
        if (size == elementDatas.size) {
            val newArray = arrayOfNulls<Any?>(size*2)
            println("   当前数据容量不够用,需要扩容,新的数据大小为:${newArray.size}")
            System.arraycopy(elementDatas, 0, newArray, 0, elementDatas.size)
            elementDatas = newArray
        }
    }

    /**
     * 对索引下标进行合法性检查
     */
    private fun rangeCheck(index: Int) {
        if (index < 0 || index >= size) {
            try {
                throw Exception()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

3 示例调用

3.1 main()

package com.sufadi.study.arrayList

class MyArrayListRunTest {

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val myArrayList = MyArrayList()
            println("1. 测试add()函数: 填充1~10的数据")
            for (i in 1..10) {
                myArrayList.add(i)
            }
            println("   查看数组的大小:${myArrayList.size}")
            for (i in 0 until myArrayList.size) {
                println("   Index = $i, get()函数:${myArrayList.get(i)}")
            }

            println("2. 测试扩容ensureCapacity(): 填充超过默认扩容大小的数据,例如hello world")
            myArrayList.add("hello world")
            println("   查看数组的大小:${myArrayList.size}")
            for (i in 0 until myArrayList.size) {
                println("   Index = $i, get()函数:${myArrayList.get(i)}")
            }


            println("3. 测试删除remove()函数,例如删除index 3")
            myArrayList.remove(3)
            println("   查看数组的大小:${myArrayList.size}")
            for (i in 0 until myArrayList.size) {
                println("   Index = $i, get()函数:${myArrayList.get(i)}")
            }
        }
    }
}

3.2 运行结果


1. 测试add()函数: 填充1~10的数据
   查看数组的大小:10
   Index = 0, get()函数:1
   Index = 1, get()函数:2
   Index = 2, get()函数:3
   Index = 3, get()函数:4
   Index = 4, get()函数:5
   Index = 5, get()函数:6
   Index = 6, get()函数:7
   Index = 7, get()函数:8
   Index = 8, get()函数:9
   Index = 9, get()函数:10
2. 测试扩容ensureCapacity(): 填充超过默认扩容大小的数据,例如hello world
   当前数据容量不够用,需要扩容,新的数据大小为:20
   查看数组的大小:11
   Index = 0, get()函数:1
   Index = 1, get()函数:2
   Index = 2, get()函数:3
   Index = 3, get()函数:4
   Index = 4, get()函数:5
   Index = 5, get()函数:6
   Index = 6, get()函数:7
   Index = 7, get()函数:8
   Index = 8, get()函数:9
   Index = 9, get()函数:10
   Index = 10, get()函数:hello world
3. 测试删除remove()函数,例如删除index 3
   remove index=3, 数组整体移动1位,将index(4 到11)区域整体放到(3 到 10)区域
   查看数组的大小:11
   Index = 0, get()函数:1
   Index = 1, get()函数:2
   Index = 2, get()函数:3
   Index = 3, get()函数:5
   Index = 4, get()函数:6
   Index = 5, get()函数:7
   Index = 6, get()函数:8
   Index = 7, get()函数:9
   Index = 8, get()函数:10
   Index = 9, get()函数:hello world
   Index = 10, get()函数:null

Process finished with exit code 0

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值