Java 的 ArrayList 的底层数据结构

1. 数据结构--ArrayList源码摘要

Java代码 
  1. public class ArrayList<E> extends AbstractList<E>  
  2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
  3. {  
  4.     ......  
  5.   
  6.     /** 
  7.      * The array buffer into which the elements of the ArrayList are stored. 
  8.      * The capacity of the ArrayList is the length of this array buffer. 
  9.      */  
  10.     private transient E[] elementData;  
  11.   
  12.   
  13.     /** 
  14.      * The size of the ArrayList (the number of elements it contains). 
  15.      * 
  16.      * @serial 
  17.      */  
  18.     private int size;  
  19.    ......  
  20. }  

 

 

 

ArrayList 的底层最重要的两个属性:Object 数组和 size 属性。

 

 

2. ArrayList 的底层数组的调整

add方法--ArrayList源码摘要

Java代码 
  1.    public boolean add(E o) {  
  2. ensureCapacity(size + 1);  // Increments modCount!!  
  3. elementData[size++] = o;  
  4. return true;  
  5.    }  

 

 

ensureCapacity方法--ArrayList源码摘要

Java代码 
  1.    public void ensureCapacity(int minCapacity) {  
  2. modCount++;  
  3. int oldCapacity = elementData.length;  
  4. if (minCapacity > oldCapacity) {  
  5.     Object oldData[] = elementData;  
  6.     int newCapacity = (oldCapacity * 3)/2 + 1;  
  7.         if (newCapacity < minCapacity)  
  8.     newCapacity = minCapacity;  
  9.     elementData = (E[])new Object[newCapacity];  
  10.     System.arraycopy(oldData, 0, elementData, 0, size);  
  11. }  
  12.    }  

 

 

2点结论:

  a. ArrayList 是通过将底层 Object 数组复制的方式(System.arraycopy方法)来处理数组的增长;

  b. 当ArrayList 的容量不足时,其扩充容量的方式:先将容量扩充至当前容量的1.5倍,若还不够,则将容量扩充至当前需要的数量。

(见代码: int newCapacity = (oldCapacity * 3)/2 + 1;

          if (newCapacity < minCapacity)
           newCapacity = minCapacity;

)

 

 

顺便看看 remove 方法

remove 方法--ArrayList源码摘要

Java代码 
  1.    public boolean remove(Object o) {  
  2. if (o == null) {  
  3.            for (int index = 0; index < size; index++)  
  4.     if (elementData[index] == null) {  
  5.         fastRemove(index);  
  6.         return true;  
  7.     }  
  8. else {  
  9.     for (int index = 0; index < size; index++)  
  10.     if (o.equals(elementData[index])) {  
  11.         fastRemove(index);  
  12.         return true;  
  13.     }  
  14.        }  
  15. return false;  
  16.    }  

 

 

fastRemove 方法--ArrayList源码摘要

Java代码 
  1. private void fastRemove(int index) {  
  2.     modCount++;  
  3.     int numMoved = size - index - 1;  
  4.     if (numMoved > 0)  
  5.         System.arraycopy(elementData, index+1, elementData, index,   
  6.                          numMoved);  
  7.     elementData[--size] = null// Let gc do its work  
  8. }  

 

 

private void fastRemove(int index) 可见,ArrayList 的元素移除后,也是通过 Object 数组复制的方式(System.arraycopy方法)来处理数组的变化; size 总是记录着当前的数组元素的数量。

 

 

这也就解释了 ArrayList 的特点:增加、删除和移动元素的效率低(数组复制过程消耗资源较多); 而查找元素和更新元素的效率高。(如下所示)

 

get 方法--ArrayList 源码摘要

Java代码 
  1.    public E get(int index) {  
  2. RangeCheck(index);  
  3.   
  4. return elementData[index];  
  5.    }  

 

 

set 方法--ArrayList 源码摘要

Java代码 
  1.    public E set(int index, E element) {  
  2. RangeCheck(index);  
  3.   
  4. E oldValue = elementData[index];  
  5. elementData[index] = element;  
  6. return oldValue;  
  7.    }  

 

 

 

3. ArrayList与Vector的区别

 

1) vector 是线程同步的,所以它也是线程安全的,而arraylist 是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用 arraylist效率比较高。

 

2)如果集合中的元素的数目大于目前集合数组的长度时,vector 增长率为目前数组长度的100%, 而arraylist 增长率为目前数组长度的50% .如果在集合中使用数据量比较大的数据,用vector有一定的优势。

 

3)如果查找一个指定位置的数据,vector和arraylist使用的时间是相同的,都是O(1) ,这个时候使用vector和arraylist都可以。

 

而如果移动一个指定位置的数据花费的时间为O(n-i)n为总长度,这个时候就应该考虑到使用linklist ,因为它移动一个指定位置的数据所花费的时间为0(1),而查询一个指定位置的数据时花费的时间为0(i)。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值