• Java集合实现(一) ArrayList源码以及手写ArrayList


    一、ArrayList集合介绍

    简单来说,它就是一个动态数组

    普通的数组一旦长度确认,长度就不再能改变。

    而该ArrayList不一样,长度可变,就是一个动态大小的数组。

    【底层代码】

     【继承关系】

     二、主要方法实现原理

    1、add方法

    • public boolean add(E e) :数组末尾直接添加元素
    • public void add(int index, E element) :指定下标位置添加元素

     public boolean add(E e)实现:这里的扩容后面再说明

    1. public boolean add(E e) {
    2. ensureCapacity(); //扩容
    3. this.elementData[size++] = e;
    4. return true;
    5. }

     public void add(int index, E element)实现:

    1. public void add(int index, E element) {
    2. if (index < 0 || index >= this.size) {
    3. throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
    4. }
    5. //插入位置以后元素依次向后移动一个位置
    6. for (int i = size; i > index; i--) {
    7. this.elementData[i] = this.elementData[i - 1];
    8. }
    9. this.elementData[index] = element;
    10. }

     2、删除指定位置元素

    删除指定下标位置元素,删除位置以后元素依次向前移动一个位置

    删除结果,可以访问的区域减一,末尾区域记得置为空,才可以被垃圾回收。 

     public E remove(int index)实现

    1. public E remove(int index) {
    2. if (index < 0 || index >= this.size) {
    3. throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
    4. }
    5. E deleteValue = elementData(index);
    6. //删除位置以后元素依次向前移动一个位置
    7. for (int i = index; i < size; i++) {
    8. this.elementData[i] = this.elementData[i + 1];
    9. }
    10. this.elementData[--size] = null;
    11. return deleteValue;
    12. }

     3、ArrayList的扩容机制

    看看ArrayList底层代码,如果没有设置大小,默认大小为10。所以只要不断插入数据,超过10个一定会越界,此时必须进行扩容。

     下面是ArrayList底层扩容,官方是进行1.5倍大小的扩容(目的是既申请了一些空间,又不会申请太多,浪费空间,即最佳实践的结果)

     笔者实现的简单扩容代码:

    1. public void ensureCapacity() {
    2. if (size < this.elementData.length) {
    3. return;
    4. }
    5. int newSize = elementData.length + (elementData.length >> 1); //原来数组大小的1.5倍
    6. if (newSize < 0) {
    7. throw new OutOfMemoryError();
    8. }
    9. elementData = Arrays.copyOf(elementData, newSize);
    10. }

    4、实现迭代器接口,暴露数组遍历功能

     【自实现代码】:

    1. public class ArrayList implements Iterable {
    2. @Override
    3. public Iterator iterator() {
    4. return new ArrayListIterator();
    5. }
    6. private class ArrayListIterator implements Iterator {
    7. int currIndex = 0;
    8. @Override
    9. public boolean hasNext() {
    10. return currIndex != size;
    11. }
    12. @Override
    13. public E next() {
    14. return elementData(currIndex++);
    15. }
    16. }
    17. }

     5、完整实现代码

    1. public class ArrayList implements Iterable {
    2. private static final int DEFAULT_CAPACITY = 10;
    3. private Object[] elementData;
    4. private int size;
    5. public ArrayList() {
    6. this.elementData = new Object[DEFAULT_CAPACITY];
    7. }
    8. private String outOfBoundsMsg(int index) {
    9. return "Index: " + index + ", Size: " + this.size;
    10. }
    11. private void rangeCheck(int index) {
    12. if (index < 0 || index >= this.size) {
    13. throw new ArrayIndexOutOfBoundsException(outOfBoundsMsg(index));
    14. }
    15. }
    16. public void ensureCapacity() {
    17. if (size < this.elementData.length) {
    18. return;
    19. }
    20. int newSize = elementData.length + (elementData.length >> 1); //原来数组大小的1.5倍
    21. if (newSize < 0) {
    22. throw new OutOfMemoryError();
    23. }
    24. elementData = Arrays.copyOf(elementData, newSize);
    25. }
    26. public E get(int index) {
    27. rangeCheck(index);
    28. return elementData(index);
    29. }
    30. private E elementData(int index) {
    31. return (E) elementData[index];
    32. }
    33. public E set(int index, E element) {
    34. rangeCheck(index);
    35. E oldValue = elementData(index);
    36. this.elementData[index] = element;
    37. return oldValue;
    38. }
    39. public boolean add(E e) {
    40. ensureCapacity(); //扩容
    41. this.elementData[size++] = e;
    42. return true;
    43. }
    44. public void add(int index, E element) {
    45. rangeCheck(index);
    46. //插入位置以后元素依次向后移动一个位置
    47. for (int i = size; i > index; i--) {
    48. this.elementData[i] = this.elementData[i - 1];
    49. }
    50. this.elementData[index] = element;
    51. }
    52. public E remove(int index) {
    53. rangeCheck(index);
    54. E deleteValue = elementData(index);
    55. //删除位置以后元素依次向前移动一个位置
    56. for (int i = index; i < size; i++) {
    57. this.elementData[i] = this.elementData[i + 1];
    58. }
    59. this.elementData[--size] = null;
    60. return deleteValue;
    61. }
    62. public void clear() {
    63. Arrays.fill(this.elementData, null);
    64. this.size = 0;
    65. }
    66. public int size() {
    67. return this.size;
    68. }
    69. public boolean isEmpty() {
    70. return this.size == 0;
    71. }
    72. @Override
    73. public Iterator iterator() {
    74. return new ArrayListIterator();
    75. }
    76. private class ArrayListIterator implements Iterator {
    77. int currIndex = 0;
    78. @Override
    79. public boolean hasNext() {
    80. return currIndex != size;
    81. }
    82. @Override
    83. public E next() {
    84. return elementData(currIndex++);
    85. }
    86. }
    87. }

    三、测试

    1. public class ArrayListTest {
    2. public static void main(String[] args) {
    3. ArrayList list = new ArrayList<>();
    4. for (int i = 0; i < 20; i++) {
    5. list.add(i);
    6. }
    7. list.remove(11);
    8. list.set(18,20);
    9. list.add(21);
    10. for (Integer integer : list) {
    11. System.out.print(integer+" ");
    12. }
    13. System.out.println();
    14. list.clear();
    15. System.out.println(list.size());
    16. }
    17. }

    【测试结果】 

     总之,ArrayList底层有很多奥秘,比如深克隆浅客隆问题、序列化等等,加油努力探索吧!!

    完结撒花……

  • 相关阅读:
    记录一次数据库CPU被打满的排查过程
    xcode SDK does not contain ‘libarclite‘
    PyCharm 常用快捷键
    SkiaSharp 之 WPF 自绘 粒子花园(案例版)
    消失的“金九银十” 互联网的下一个五年在哪里?
    嵌入式分享合集42
    行业缩减他却增加!海尔智家研发投入创新高
    C++智能指针与类型转换
    如何从任何苹果、Windows或安卓设备访问iCloud照片
    ISO20000认证一般要多少钱
  • 原文地址:https://blog.csdn.net/m0_46013789/article/details/126753191