ArrayList jdk1.8源码分析

 

一、ArrayList简述:

  

  ArrayList是线程非安全的数组列表,优势在于数组结构,查询效率高,修改效率较低;由下图的类图,可以看出
ArrayList是可以序列化,复制的;


 

 

二、构造函数

  1、自定义初始化容量大小,int类型,值为非负数

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

  2、无参构造,此时数组为空,直到第一次添加元素时,才会定义为默认初始化大小10

 

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

  3、带Collection对象,将Collection对象转换为数组,并将引用赋予elementData,若对象有值,利用System.copy赋值给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;
    }
}

三、常用方法

  1. 最常用的添加元素,add的两个方法:
public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
}
  • 判断 elementData  是否需要扩容,并且记录 modCount 增一,表示一次列表大小的修改
    1. 检查 elementData  是否已经初始化过大小,如果没有,则进行第一次分配空间,分配默认空间大小与需要的空间大小中更大的值所需空间(可能第一次调用的就是addAll(Collection<? extends E> c)方法,导致第一次分配空间就不是默认大小)
      private void ensureCapacityInternal(int minCapacity) {
              if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                  minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
              }
      
              ensureExplicitCapacity(minCapacity);
      }
    2. modCount++;记录一次大小的变更,然后判断是否需要扩容

      private void ensureExplicitCapacity(int minCapacity) {
              modCount++;
      
              // overflow-conscious code
              if (minCapacity - elementData.length > 0)
                  grow(minCapacity);
      }

       

    3. 扩容操作;首先获得原先的数组的elementData长度,然后获得大约原空间的1.5倍的大小(此处使用位操作,提高效率);然后是判断1.5倍空间是否满足需求,满足,则赋值为需要的空间(但是minCapacity可能会超过int取值范围上限,所以需要下一步);接着如果minCapacity超过上限抛出OOM,否则判断minCapacity是否超过数组的缺省上限,超过:int上限,不超过:数组缺省上限(Integer.MAX_VALUE - 8,这是由于jvm中数组头部会存储长度信息,但是这里在minCapacity超过缺省上限以后,允许给到int上限,我也不知道原因,如果有知道的欢迎交流);最后执行Arrays.copyOf,将原数组数据copy到新数组中

      private void grow(int minCapacity) {
              // overflow-conscious code
              int oldCapacity = elementData.length;
              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;
      }

       

  • 将指定添加元素,添加至elementData数组的末尾

 

2、contains方法,仅仅是遍历列表数据,直到找寻到数据为止;如果数据量较大,建议使用HashSet(基于HashMap的方式)

public boolean contains(Object o) {
        return indexOf(o) >= 0;
}

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;
}

3、clear方法,遍历列表,将数组引用指向null,但是数组本身长度不变,仍然占用内存,引用对象所占内存需要等gc判断是否有其它引用后选择回收与否。

public void clear() {
        modCount++;

        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            // 将数组引用指向null
            elementData[i] = null;

        size = 0;
}

 

其实还有些方法值得看一下,等后面有时间再去补充吧......

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值