Java集合ArrayList数组实现原理及源码分析详解_一点课堂(多岸学院)

arraylist源码分析

  1. 数组介绍

    数组是数据结构中很基本的结构,很多编程语言都内置数组。

    在java中当创建数组时会在内存中划分出一块连续的内存,然后当有数据进入的时候会将数据按顺序的存储在这块连续的内存中。当需要读取数组中的数据时,需要提供数组中的索引,然后数组根据索引将内存中的数据取出来,返回给读取程序。在Java中并不是所有的数据都能存储到数组中,只有相同类型的数据才可以一起存储到数组中。

    img

    因为数组在存储数据时是按顺序存储的,存储数据的内存也是连续的,所以他的特点就是寻址读取数据比较容易,插入和删除比较困难

  2. arraylist源码分析

    • 构造方法

      public ArrayList(int initialCapacity) {
          if (initialCapacity > 0) {
              // 创建指定长度的object数组
              this.elementData = new Object[initialCapacity];
          } else if (initialCapacity == 0) {
              // 空数组
              this.elementData = EMPTY_ELEMENTDATA;
          } else {
              throw new IllegalArgumentException("Illegal Capacity: "+
                                                 initialCapacity);
          }
      }
      
      // 空参构造方法
      public ArrayList() {
          this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
      }
      
      public ArrayList(Collection<? extends E> c) {
          elementData = c.toArray();
          if ((size = elementData.length) != 0) {
              // c.toArray might (incorrectly) not return Object[] (see 6260652)
              if (elementData.getClass() != Object[].class)
                  elementData = Arrays.copyOf(elementData, size, Object[].class);
          } else {
              // replace with empty array.
              this.elementData = EMPTY_ELEMENTDATA;
          }
      }
    • 插入数据

      public boolean add(E e) {
          // 检测是否需要扩容
          ensureCapacityInternal(size + 1);  // Increments modCount!!
          // 数组赋值
          elementData[size++] = e;
          return true;
      }
      
      public void add(int index, E element) {
          // 判断index是否越界
          rangeCheckForAdd(index);
          // 检测是否需要扩容
          ensureCapacityInternal(size + 1);  // Increments modCount!!
          // 将index之后的所有元素向后移动一位
          System.arraycopy(elementData, index, elementData, index + 1,
                           size - index);
          // 将index位置覆盖新值
          elementData[index] = element;
          size++;
      }
      
      // 扩容的入口方法
      private void ensureCapacityInternal(int minCapacity) {
          ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
      }
      
      // 计算最小容量
      private static int calculateCapacity(Object[] elementData, int minCapacity) {
          if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
              // 默认容量10
              return Math.max(DEFAULT_CAPACITY, minCapacity);
          }
          return minCapacity;
      }
      
      private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
      
          // overflow-conscious code
          // 是否满足扩容的条件 最小容量 - object数组的长度
          if (minCapacity - elementData.length > 0)
              grow(minCapacity);
      }
      // 数组扩容方法
      private void grow(int minCapacity) {
          // overflow-conscious code
          // 当前数组长度
          int oldCapacity = elementData.length;
          // 新的数组容量 = 老容量 + 老容量/2 (1.5倍)
          // oldCapacity = 10
          // oldCapacity >> 1 
          //  0000 1010 >> 1 
          //  0000 0101 = 5
          int newCapacity = oldCapacity + (oldCapacity >> 1);
          if (newCapacity - minCapacity < 0)
              newCapacity = minCapacity;
          if (newCapacity - MAX_ARRAY_SIZE > 0)
              newCapacity = hugeCapacity(minCapacity);
          // minCapacity is usually close to size, so this is a win:
          elementData = Arrays.copyOf(elementData, newCapacity);
      }
    • 删除方法

      // 指定位置删除
      public E remove(int index) {
          // 检测index值,IndexOutOfBoundsException
          rangeCheck(index);
      
          modCount++;
          // 返回要删除的元素
          E oldValue = elementData(index);
         // 将index+1及之后的元素向前移动一位,覆盖被删除的值
          int numMoved = size - index - 1;
          if (numMoved > 0)
              System.arraycopy(elementData, index+1, elementData, index,
                               numMoved);
          // 将最后一个位置的元素清空
          elementData[--size] = null; // clear to let GC do its work
      
          return oldValue;
      }
      
      // 指定元素删除
      public boolean remove(Object o) {
          // 判断元素是否为null
          if (o == null) {
              for (int index = 0; index < size; index++)
                  if (elementData[index] == null) {
                      fastRemove(index);
                      return true;
                  }
          } else {
              for (int index = 0; index < size; index++)
                  if (o.equals(elementData[index])) {
                      fastRemove(index);
                      return true;
                  }
          }
          // 如果没有匹配元素,返回false
          return false;
      }
      
      // 快速删除,没有检测index下标
      private void fastRemove(int index) {
          modCount++;
          int numMoved = size - index - 1;
          if (numMoved > 0)
              System.arraycopy(elementData, index+1, elementData, index,
                               numMoved);
          elementData[--size] = null; // clear to let GC do its work
      }
    • 遍历

      ArrayList<Integer> list = new ArrayList();
      
      list.add(10);
      list.add(11);
      list.add(12);
      list.add(13);
      list.add(15);
      
      for (Integer num : list) {
          if (num == 12) {
              list.remove(num);
          }
      }
      // 报错
      // Exception in thread "main" java.util.ConcurrentModificationException
      
      final void checkForComodification() {
          // 不相等就报异常
          if (modCount != expectedModCount)
              throw new ConcurrentModificationException();
      }
      
      // 解决删除异常问题
      Iterator<Integer> it = list.iterator();
      while(it.hasNext()){
          Integer num = it.next();
          if (num == 12) {
              // 使用迭代器的删除方法
              it.remove();
          }
      }
      public void remove() {
          if (lastRet < 0)
              throw new IllegalStateException();
          checkForComodification();
      
          try {
              ArrayList.this.remove(lastRet);
              cursor = lastRet;
              lastRet = -1;
              // 修改expectedModCount和当前modCount一样
              expectedModCount = modCount;
          } catch (IndexOutOfBoundsException ex) {
              throw new ConcurrentModificationException();
          }
      }

    视频教程:http://www.yidiankt.com/

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

    一点课堂公众号
    关注公众号-免费获取【JAVA核心知识点】!!
    QQ讨论群: 706564342
    在这里插入图片描述

猜你喜欢

转载自www.cnblogs.com/yidiankt/p/11458052.html