ArrayList深度透析
阿新 • • 發佈:2018-12-15
一、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。
* 但是究竟要多大,這得取決於伺服器的配置
:在這裡實際上指的是伺服器的記憶體資源,如果伺服器記憶體資源比較
大,
* 就可以分配大一點,如果記憶體資源比較小,
就小一點。
* 這樣做的好處是減少擴容的次數,減少了擴
容的次數就減少了複製的次數。
* */
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<>
();*/
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。
* 但是究竟要多大,這得取決於伺服器的配置
:在這裡實際上指的是伺服器的記憶體資源,如果伺服器記憶體資源比較
大,
* 就可以分配大一點,如果記憶體資源比較小,
就小一點。
* 這樣做的好處是減少擴容的次數,減少了擴
容的次數就減少了複製的次數。
* */