java源码解析——ArrayList

java源码解析——ArrayList

    • 一 继承和实现
    • 二 ArrayList的内部解析

ArrayList 顾名思义 ‘数组集合’


一 继承和实现


  1. 首先看看这个ArrayList类里继承和实现了哪些类和接口
    extends AbstractList
    implements List, RandomAccess, Cloneable, java.io.Serializable

  2. 继承了AbstractList ,在AbstractList里已经实现了List接口里的方法。我们知道继承就是为了增强父类的一些方法 比如 AbstractList 里面的add方法 他只是抛出了异常 没有做其他的操作 我们的ArrayList肯定用到这个add方法 所以ArrayList里面 重写父类的这个方法。至于为啥AbstractList add方法只抛出异常而不做操作 是因为有的集合不允许做add的操作 比如一个不能修改的集合 你如果调用add 就会抛这个UnsupportedOperationException异常。这里就显示了开发人员的设计思想。

  3. 其次 实现了List接口 这里有个疑问 为啥abstractList已经实现了List 为啥这里还去实现以下List 我直接重写父类不就行了?搞这个操作是啥目的呢?我觉得它有意向揭示arraylist的目标是实现List,扩展AbstractList抽象类只是实现该目标的一种方式,毕竟AbstractList都实现了一些方法我干嘛还是要去搞一遍呢?哈哈哈。

  4. RandomAccess Cloneable java.io.Serializable 这些接口应该都了解不多做了解。


二 ArrayList的内部解析


  1. ArrayList里主要是维护了一个Object类型的数组,elementData。
  2. 默认容量 是10 —— DEFAULT_CAPACITY = 10。
  3. 三个构造方法 第一个: 默认的构造方法 直接将elementData赋值成DEFAULTCAPACITY_EMPTY_ELEMENTDATA 也就是一个空的数组 第二个: 接受一个 initialCapacity 初始化的容量 大于0则new Object[initialCapacity]; 等于0 则还是赋值一个空数组 小于0 抛出自定义的异常信息Illegal Capacity。第三个:接受一个Collection 将 这个参数toarray 赋值给elementData 如果这个elementData 的长度不为0 判断是否是object类型的数组 如果不是的 重新copy一份 elementData不是obj类型的数组转成elementData 为obj类型的数组。为啥这样做 源码有一段注释 // c.toArray might (incorrectly) not return Object[] (see 6260652) 意思是传过来的参数转成数组后可能不能返回 Object[] 所以得将其转成 Object[]。如果等于0 还是给个默认的空数组。

方法trimToSize:
修剪此ArrayList实例的容量
*列表的当前大小。应用程序可以使用此操作来最小化
*存储ArrayList实例

     public void trimToSize() {
        modCount++;//记录操作的次数
        //判断如果数组的长度大于ArrayList的本身size那么就将其缩减为他本身的size。
        if (size < elementData.length) {
        //size是0的 直接赋值空数组 否则就是重新copy出一份size长度大小的数组重新赋值给elementData。
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }
    

方法ensureCapacityInternal 目的计算并确保容量 这里是ArrayList增长的计算算法他的容量增长公式是 int newCapacity = oldCapacity + (oldCapacity >> 1); 哇 不想当数学家的程序员不是好司机 数学还是很重要的。

 private void ensureCapacityInternal(int minCapacity) {
 //如果elementData是空数组 那么初始化的时候用的容量 是从初始10和传入的数组中找一个最大的值作为初始化的值 如果不是空数组那么就将传参作为初始化的容量
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
          //确保明确的容量
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
    //还是记录操作的次数
        modCount++;

        // overflow-conscious code 传入的最小初始化参数减去数组的长度大于0 说明要进行数组扩容了
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

 private void grow(int minCapacity) {
        // overflow-conscious code 获取旧的数组长度
        int oldCapacity = elementData.length;
        //新的长度是用旧的长度加上旧的长度一半 增长因子1.5  这是为何?需要了解的点击这个网址https://stackoverflow.com/questions/4450628/arraylist-how-does-the-size-increase
        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);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

方法contains 判断一个element 参数是否在这个集合里
这个实现的方式就是循环数组 找到这个对应的element的index 如果index存在则返回true
方法indexof 找到这个element参数的index 也就是上面所说的循环数组找值的index
如果是个null对象 找到这个null的位置返回index

 public int indexOf(Object o) {
        if (o == null) {
            for (int i = 0; i < size; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }

方法lastIndexOf 跟indexof恰恰相反 循环是 从size开始 i–

方法toArray 这个就比较简单了 就是调用copyof 重新复制一份elementData 返回出去
toarray还有一个返回T类型的数组 原理一样

你可能感兴趣的:(java源码解析——ArrayList)