ArrayList 源码分析

在我们刚学Java时老师一定会说ArrayList是很好用的变长数组,你只要尽管插入删除就可以了,比C++的数组控制简单多了,
ArrayList是典型的自增长数组。

private int size;  //数组中实际元素的数量
capacity表示数组的总大小,比如arr = new int[5],则capacity=5.


//initialCapacity为初始的数组大小,因为自增长数组的缺点就是重新分配数组时会耗费内存,
重新分配就意味着原空间的垃圾生成加重垃圾回收的负担,
因此如果一开始分配的大一点,以后就会避免重新分配的次数


比如你如果要插入200个元素,则:
(1)一开始就分配200个元素的capacity,则一次分配
(2)一开始分配1个,不够了再多分配1个,如果没有垃圾回收,则1+2+3+......200=20100个空间
200和20100,差别很大吧。


先回顾下ArrayList中最核心的两个语句:

int[]newarr = Arrays.copyOf(int[]old,int newlength);
//newarr = Arrays.copyOf(oldarr,newlength);  
//表示将oldarr的全部内容复制到newarr中,newarr的长度为newlength


System.arraycopy(oldarr, oldbegin, newarr, newbegin,length);
//将oldarr中的第oldbegin开始,长度为length的子数组复制到newarr的从newbegin开始的位置处。
比如oldarr={1,2,3}. newarr={5,6,7},oldbegin=1,newbegin=1,length=2.则执行后,结果为newarr为{5,2,3}.
比如oldarr={1,2,3,4}. newarr={5,6,7},oldbegin=1,newbegin=1,length=3.则执行后,结果为ArrayOutofBoundsException,因为newarr长度不够


[java]  view plain copy
  1. public ArrayList(int initialCapacity) {   
  2.         if (initialCapacity < 0)  
  3.             throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);  
  4.     this.elementData = new Object[initialCapacity];  
  5. }  


[java]  view plain copy
  1. //默认开始分配的大小10  
  2. public ArrayList() {  
  3.     this(10);  
  4. }  


//如果当前capacity<minCapacity,则将数组的capacity增长到minCapacity
[java]  view plain copy
  1. public void ensureCapacity(int minCapacity) {  
  2.     int oldCapacity = elementData.length;  
  3.     if (minCapacity > oldCapacity) {  
  4.         Object oldData[] = elementData;  
  5.         int newCapacity = (oldCapacity * 3) / 2 + 1;    //newlength = (oldlength*3)/2+1  
  6.         if (newCapacity < minCapacity)  
  7.             newCapacity = minCapacity;  
  8.         elementData = Arrays.copyOf(elementData, newCapacity);  //此语句是自增长数组的核心语句  
  9.     }  
  10. }  


添加元素

[java]  view plain copy
  1. public boolean add(E e) {  
  2.     ensureCapacity(size + 1); //将size+1,如果capacity不够,则重新分配  
  3.     elementData[size++] = e;  
  4.     return true;  
  5. }  


添加多个元素


[java]  view plain copy
  1. public boolean addAll(Collection<? extends E> c) {  
  2.     Object[] a = c.toArray();  
  3.     int numNew = a.length;  //新插入的元素大小  
  4.     ensureCapacity(size + numNew); //插入元素钱首先判断容量够不够  
  5.     System.arraycopy(a, 0, elementData, size, numNew);  //将a[0,...a,length-1] 放到 elementData[size,....size+numNew-1]中去  
  6.     size += numNew;   
  7.     return numNew != 0;  
  8. }  



移除元素
[java]  view plain copy
  1. public E remove(int index) {  
  2.     RangeCheck(index);  //看index是否在数组的界里  
  3.     E oldValue = (E) elementData[index];  
  4.     int numMoved = size - index - 1;  
  5.     if (numMoved > 0)  
  6.         System.arraycopy(elementData, index + 1, elementData, index,numMoved);  
  7.     elementData[--size] = null//使得垃圾回收器将其回收  
  8.     return oldValue;  
  9. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值