• 数据结构-ArrayList解析和实现代码


    arrayList结构的实现是数组结构,数组没有扩容机制,arrayList的扩容机制采用的是复制数组,了解你会发现ArrayList虽然实现比较简单,但是设计还是很巧妙的。咱们先来简单实现下..

    咱们看下定义的全局变量

    1.默认初始化空间为10,也就是默认数组空间大小

    2.定义个空元素

    3.顶一个数组存储元素

    4.数组长度

    5.构造方法默认给个空元素

    1. // 默认初始化空间
    2. private static final int DEFAULT_CAPACITY = 10;
    3. // 空元素
    4. private static final Object[] DEFAULTCAPACITY_EMPTY_ELMENTDATA = {};
    5. // ArrayList元素数组缓冲区
    6. transient Object[] elementData;
    7. // List 集合元素数量
    8. private int size;
    9. public ArrayList() {
    10. // 默认给个空的元素,当开始添加元素的时候在初始化长度
    11. this.elementData = DEFAULTCAPACITY_EMPTY_ELMENTDATA;
    12. }

    1.添加元素

    添加就是将数据存储到上边定义的elementData数组里,需要按数组下标一个个的排好存储,但是如果超出了默认的数组长度10怎么办?需要新开辟空间,把原数组原封不动的放回原有的位置,接下来看下代码。

    第一次添加元素时

      1.1 size为0,minCapacity得到的就是1,因为数据都是空,所以minCapacity设置了默认值10

       1.2 10-0 肯定大于0,创建数组空间,那么当数组存储10条时这个minCapacity就是11,11-10大于0,需要扩容了还是运用了一个操作,这块设计的就很好

       1.3 当需要扩容时找到旧数组的长度,然后用旧数组的长度+旧数组长度除以2,也就是除了第一次扩容是10,第二次就是15。

        1.4 新要开辟的数字小于之前的minCapacity,newCapacity - minCapacity,那就把minCapacity赋值给newCapacity,在第一次存储数据就是这样,newCapacity=0,minCapacity=10,就需要赋值

        1.5 通过Arrays.copyof(数组,长度); 开辟空间,扩容也是如此

        1.6 然后存储数据,返回成功

    第二次添加元素时

    minCapacity=2,判断扩容2-10是小于0的,不扩容,直接存储返回数据

    1. // 添加
    2. public boolean add(E e) {
    3. int minCapacity = size + 1;
    4. if (elementData == DEFAULTCAPACITY_EMPTY_ELMENTDATA) {
    5. minCapacity = DEFAULT_CAPACITY;
    6. }
    7. // 判断是否数组容量不足
    8. if (minCapacity - elementData.length > 0) {
    9. int oldCapacity = elementData.length;
    10. // 加原来数组长度+将原来数组长度除2
    11. int newCapacity = oldCapacity + (oldCapacity >> 1);
    12. // 扩展数据比原最小容量小就直接赋值minCapacity
    13. if (newCapacity - minCapacity < 0) {
    14. newCapacity = minCapacity;
    15. }
    16. // 进行复制原数组操作
    17. elementData = Arrays.copyOf(elementData, newCapacity);
    18. }
    19. // 存储数据
    20. elementData[size++] = e;
    21. return true;
    22. }

    2.获取元素

    获取元素非常简单,根据下标获取元素即可

    1. // 根据索引查询
    2. public E get(int index) {
    3. return (E) elementData[index];
    4. }

    3.删除元素

    删除元素需要考虑移动元素的情况,假如1-2-3-4,删除2以后数组就是134,3的下标就是1,而不是以前的2。

    根据System.arraycopy进行解决移动数据问题,假如现有1-2-3-5-8数据,删除了3也就是小标2的数据,那么原数组的拷贝需要从index+1开始,也就是不拷贝3的元素,拷贝到目标元素还是elementData,从index位置也就是3的位置开始拷贝,拷贝几个数据呢,需要拷贝size-index-1,也就是说5-2-1=2,拷贝两个就是5和8到elementData,这样数组最后就剩1-2-5-8,其实就是挤出去的,是不是设计很巧妙,拷贝完后将长度减1,并把数组最后一个元素置为空

    1. public E remove(int index) {
    2. E e = get(index);
    3. // 总共拷贝多条数据
    4. int numMoved = size - index - 1;
    5. if (numMoved > 0) {
    6. // 把elementData元素进行拷贝,从index+1(就是当前要删除的下一个元素开始)
    7. // 拷贝到elementData元素,从index下标为止,赋值后所有的数据
    8. System.arraycopy(elementData, index + 1, elementData, index, numMoved);
    9. }
    10. elementData[--size] = null;
    11. return e;
    12. }

    4.更新

    更新则和获取一样,通过下标元素找到值直接赋当前值

    1. // 更新
    2. public boolean set(int index, E e) {
    3. elementData[index] = e;
    4. return true;
    5. }

    全部代码

    1. package linkedList;
    2. import java.util.Arrays;
    3. import java.util.List;
    4. /**
    5. * @Author df
    6. * @Date 2022/11/20 15:16
    7. * @Version 1.0
    8. */
    9. public class ArrayList {
    10. // 默认初始化空间
    11. private static final int DEFAULT_CAPACITY = 10;
    12. // 空元素
    13. private static final Object[] DEFAULTCAPACITY_EMPTY_ELMENTDATA = {};
    14. // ArrayList元素数组缓冲区
    15. transient Object[] elementData;
    16. // List 集合元素数量
    17. private int size;
    18. public ArrayList() {
    19. // 默认给个空的元素,当开始添加元素的时候在初始化长度
    20. this.elementData = DEFAULTCAPACITY_EMPTY_ELMENTDATA;
    21. }
    22. // 添加
    23. public boolean add(E e) {
    24. int minCapacity = size + 1;
    25. if (elementData == DEFAULTCAPACITY_EMPTY_ELMENTDATA) {
    26. minCapacity = DEFAULT_CAPACITY;
    27. }
    28. // 判断是否数组容量不足
    29. if (minCapacity - elementData.length > 0) {
    30. int oldCapacity = elementData.length;
    31. // 加原来数组长度+将原来数组长度除2
    32. int newCapacity = oldCapacity + (oldCapacity >> 1);
    33. // 扩展数据比原最小容量小就直接赋值minCapacity
    34. if (newCapacity - minCapacity < 0) {
    35. newCapacity = minCapacity;
    36. }
    37. // 进行复制原数组操作
    38. elementData = Arrays.copyOf(elementData, newCapacity);
    39. }
    40. // 存储数据
    41. elementData[size++] = e;
    42. return true;
    43. }
    44. // 根据索引查询
    45. public E get(int index) {
    46. return (E) elementData[index];
    47. }
    48. public E remove(int index) {
    49. E e = get(index);
    50. // 总共拷贝多条数据
    51. int numMoved = size - index - 1;
    52. if (numMoved > 0) {
    53. // 把elementData元素进行拷贝,从index+1(就是当前要删除的下一个元素开始)
    54. // 拷贝到elementData元素,从index下标为止,赋值后所有的数据
    55. System.arraycopy(elementData, index + 1, elementData, index, numMoved);
    56. }
    57. elementData[--size] = null;
    58. return e;
    59. }
    60. // 更新
    61. public boolean set(int index, E e) {
    62. elementData[index] = e;
    63. return true;
    64. }
    65. public void print() {
    66. for (Object o : elementData) {
    67. System.out.print("-" + o);
    68. }
    69. System.out.println("");
    70. }
    71. public static void main(String[] args) {
    72. List list = new java.util.ArrayList();
    73. list.add("1111");
    74. System.out.println("插入元素----");
    75. ArrayList arrayList = new ArrayList();
    76. arrayList.add("1");
    77. arrayList.add("2");
    78. arrayList.add("3");
    79. arrayList.add("5");
    80. arrayList.add("8");
    81. arrayList.print();
    82. System.out.println("获取元素----");
    83. System.out.println(arrayList.get(2));
    84. System.out.println("删除元素----");
    85. arrayList.remove(2);
    86. arrayList.print();
    87. System.out.println("更新元素----");
    88. arrayList.set(2, "3");
    89. arrayList.print();
    90. }
    91. }

    执行结果 

     

  • 相关阅读:
    将Windows文件复制,改装成游戏
    旧版elasticsearch 2.3.4 集群部署过程
    vue-puzzle-vcode完成验证码拖拽
    doris写入超时
    Python的第三方日志库Loguru
    Target EDI 对接详解 – Partner Online EDI 注册
    排序5:直接选择排序
    碰瓷 MongoDB?MangoDB 正式改名为 FerretDB;谷歌和高通将在神经网络方面进行合作;PyCharm 2021.3 发布 | 开源日报
    【愚公系列】2022年07月 Tabby集成终端的使用
    JS-Number数字类型详解
  • 原文地址:https://blog.csdn.net/dfBeautifulLive/article/details/128054176