1. 程式人生 > >ArrayList深度透析

ArrayList深度透析

一、ArrayList


1、問你ArrayList初始容量是多少?


如果使用無引數的建構函式僅僅建立而不新增任何元素,那麼容量是


0;
如果添加了元素,則容量擴充套件為初始容量10.
ArrayList底層實際上是一個Object型別的陣列但是如果僅僅是建立一


個ArrayList集合,實際上這個時候指向是一個空(empty)的集合,長


度是0。我們一旦開始呼叫add方法想集合中新增元素的時候,這個時


候實際上是建立初始容量為10的陣列。


 確保存放集合元素的陣列的容量是足夠的
 在呼叫add()函式的時候,會首先呼叫: 


ensureCapacityInternal()  
 
ArrayList的擴容策略:
1、如果集合的容量不夠,就要呼叫grow函式擴容,擴容本質上是建立


一個容量更大的新的陣列,然後把原來陣列中的元素拷貝到新的陣列


當中來:Arrays.copyOf()實現元素的拷貝。
2、新的陣列的容量究竟是多大:oldCapacity+(oldCapacity >> 1)  


容量擴充套件方案
3、是當前陣列已經填滿了,那麼才開始擴容。即ArrayList的負載因


子是1


該add實際上是把元素新增到陣列的末尾【該末尾不是指陣列的末尾,


而是指新增的元素的下一個位置】


2、//如果不向如下所有的list集合新增元素的話,
   //那麼這些集合在記憶體中實際上指向同一個空的陣列。
/*ArrayList<String> list1=new ArrayList<>


();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>();
ArrayList<String> list1=new ArrayList<>


();*/


3、
 /* 1、使用如下add的時候,要確保指定的index要在[0-size]這個


範圍之間,否則將丟擲:IndexOutOfBoundsException。
    * 2、該add()相當於在指定索引位置插入一個元素:該索引位置後


面的元素將往後移動。
* 並且是先移動,再插入,否則,將覆蓋原來的元素。
*   【實際上,從底層原始碼來看,是一個拷貝操作。】
*    從這裡可以看出:ArrayList不適用於插入頻繁的應


用場合。
         * 3、該方法也會導致size+1
* */
list1.add(5, "v");


/**
* 在獲取指定索引位置的元素的時候,會首先檢


查該索引是否大於ArrayList的size,
* 如果大於size的話,將丟擲:


IndexOutOfBoundsExeption。
* 當然,如果指定的值小於0大於底層陣列的


length,也會丟擲IndexOutOfBoundsExeption。
* */
//System.out.println(list1.get(-2));

//ArrayList直接使用索引獲取陣列元素,效率非


常高,因此,ArrayList非常適合用於查詢頻繁的應用場合.
System.out.println(list1.get(3));


4              /**
* 刪除的邏輯不是把指定位置設定為空或者0,
* 而是把該位置後面的值往前移動,
* 最後把最後一個位置置空,
* 並且size-1
* 也就是說,刪除的位置實際上是被後面的值給


覆蓋掉。
* 因此,ArrayList實際上並不適合刪除頻繁的場


合。
* */
list1.remove(3);
  //直接根據索引修改即可  因此效率非常好  即ArrayList適合頻繁


修改的應用場合。
list1.set(3, "");
 
5 什麼時候用無參構造,什麼時候用有參構造??
   
               /**
                 * 1、如果我們不知道該集合究竟有可能存放多少


個數據,我們最好是使用無引數的建構函式建立ArrayList例項。
*   如果一開始分配很大,但是最後真正存放的


資料只有很少的資料,導致大量的記憶體空間浪費;
* 2、如果我們知道大概要往ArrayList容器中存


放多少個數據,這個時候就應當儘可能的分配一個初始容量大的


ArrayList。
*   但是究竟要多大,這得取決於伺服器的配置


:在這裡實際上指的是伺服器的記憶體資源,如果伺服器記憶體資源比較


大,
*   就可以分配大一點,如果記憶體資源比較小,


就小一點。
*   這樣做的好處是減少擴容的次數,減少了擴


容的次數就減少了複製的次數。
* */