国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴(kuò)容的

聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴(kuò)容的

2020-08-17 12:28光哥_帥 Java教程

這篇文章主要介紹了聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴(kuò)容的,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

一、結(jié)論先行

ArrayList在JDK1.8與JDK1.7底層區(qū)別

JDK1.7:ArrayList像餓漢式,直接創(chuàng)建一個初始容量為10的數(shù)組,當(dāng)數(shù)組的長度不能容下所添加的內(nèi)容時候,數(shù)組會擴(kuò)容至原大小的1.5倍

JDK1.8:ArrayList像懶漢式,一開始創(chuàng)建一個長度為0的數(shù)組,當(dāng)添加第一個元素時再創(chuàng)建一個始容量為10的數(shù)組,當(dāng)數(shù)組的長度不能容下所添加的內(nèi)容時候,數(shù)組會擴(kuò)容至原大小的1.5倍

二、JDK1.8 ArrayList源碼分析

1、ArrayList 屬性

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * 默認(rèn)容量的大小
 */
private static final int DEFAULT_CAPACITY = 10;
 
/**
 * 空數(shù)組常量
 */
private static final Object[] EMPTY_ELEMENTDATA = {};
 
/**
 * 默認(rèn)的空數(shù)組常量,我們將其與EMPTY_ELEMENTDATA區(qū)分開來,
 * 以便知道添加第一個元素時需要膨脹多少
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 
 
/**
 * 存放元素的數(shù)組,從這可以發(fā)現(xiàn)ArrayList的底層實現(xiàn)就是一個Object數(shù)組
 */
transient Object[] elementData;
 
/**
 * 數(shù)組中包含元素的個數(shù)
 */
private int size;
 
/**
 *數(shù)組的最大上限,超過上限可能導(dǎo)致OutOfMemoryError錯誤
 */
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

2、構(gòu)造方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * 指定大小的時候,elementData就變成了我們所指定的初始化大小了
 */
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);
  }
}
 
/**
 *  根據(jù)上面的屬性可知,DEFAULTCAPACITY_EMPTY_ELEMENTDATA={},所以默認(rèn)創(chuàng)建的是  一個大小為0的空數(shù)組
 */
public ArrayList() {
  this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

從上面我可以知道,jkd1.8中默認(rèn)的是大小為0空數(shù)組,這個和jdk1.7之前都是不一樣的,這和設(shè)計模式的懶漢式很有相似之處

3、add 方法,底層擴(kuò)容機(jī)制

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/**
  * 在指定的位置插入指定的元素
  */
 public void add(int index, E element) {
   rangeCheckForAdd(index);
 
   ensureCapacityInternal(size + 1); // Increments modCount!!
   System.arraycopy(elementData, index, elementData, index + 1,
            size - index);
   elementData[index] = element;
   size++;
 }
 
 /**
  * 將指定的參數(shù)添加到列表的末尾,其中size是數(shù)組中包含元素的個數(shù)
  * @param e 以附加到此列表中
  */
 public boolean add(E e) {
   ensureCapacityInternal(size + 1);
   // 數(shù)組的下標(biāo)從0開始,所以size++保證elementData每次添加完一個元素,元素個數(shù)也隨之加1
   elementData[size++] = e;
   return true;
 }
 
// 參數(shù)minCapacity 表達(dá)的意思是所需數(shù)組的最小容量,也就是size+1, 上面?zhèn)鞯闹?/code>
 private void ensureCapacityInternal(int minCapacity) {
   ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
 }
 
 
 /**
 * 計算容量的方法,
 */
 private static int calculateCapacity(Object[] elementData, int minCapacity) {
  // 如果是一個空數(shù)組,
   if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
   // DEFAULT_CAPACITY從屬性可知默認(rèn)是10,minCapactity為數(shù)組的大小
   // 由此可以看出他是在添加第一個元素的時候,才創(chuàng)建了長度為10的數(shù)組
     return Math.max(DEFAULT_CAPACITY, minCapacity);
   }
   return minCapacity;
 }
 
 
private void ensureExplicitCapacity(int minCapacity) {
   modCount++;
 // 如果此時所需要的最小的長度大于原數(shù)組的長度,則需要進(jìn)行擴(kuò)容
   if (minCapacity - elementData.length > 0)
     grow(minCapacity);
 }
 
 /**
  * 增加容量,以確保它至少可以容納minCapacity指定的元素數(shù)量。
  * @param minCapacity 表示所需要的擴(kuò)容的量
  */
 private void grow(int minCapacity) {
   int oldCapacity = elementData.length; // 原數(shù)組的長度
  //原數(shù)組的長度+原數(shù)組的長度/2,表示擴(kuò)容了原來大小的1.5倍,newCapacity :表示需要擴(kuò)容的量
   int newCapacity = oldCapacity + (oldCapacity >> 1);
   if (newCapacity - minCapacity < 0)
     newCapacity = minCapacity;
  // 如果需要的擴(kuò)容量大于了本類中定義的最大擴(kuò)容限制,則擴(kuò)容到 int 類型最大長度
   if (newCapacity - MAX_ARRAY_SIZE > 0)
     newCapacity = hugeCapacity(minCapacity);
  // 調(diào)用的是數(shù)組的復(fù)制方法,實現(xiàn)擴(kuò)容
   elementData = Arrays.copyOf(elementData, newCapacity);
 }
 
 private static int hugeCapacity(int minCapacity) {
   if (minCapacity < 0) // overflow
     throw new OutOfMemoryError();
  // 如若需要擴(kuò)容的量大于最大限制,則擴(kuò)容量改為 int 最大限制量:2147483647,否則為本類中所限制長度:2147483647-8
   return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
 }

解釋:int newCapacity = oldCapacity + (oldCapacity >> 1);

這個>>1 表示的是右移一位,轉(zhuǎn)為二進(jìn)制我們應(yīng)該一下就明白了:比如16,轉(zhuǎn)為2進(jìn)制為

10000,右移一位則成為01000,換為十進(jìn)制就是8,擴(kuò)容的大小也就相當(dāng)于oldCapacity +oldCapacity /2了

4、總結(jié)

jdk1.8中:

add方法總結(jié)起來就是在插入數(shù)據(jù)之前,會先檢查是否需要擴(kuò)容,通過無參構(gòu)造方法來創(chuàng)建 ArrayList 時,它的大小其實是為 0 的,只有在使用到 的時候,才會通過 grow 方法去創(chuàng)建一個大小為 10 的數(shù)組。

public boolean add(E e) 方法的復(fù)雜度為O(1),涉及到擴(kuò)容的操作是非常少的,可以忽略不計,它的本質(zhì)是添加元素到數(shù)組中最后一個元素的后面。

public void add(int index, E element) 這個是帶指定下標(biāo)的add 方法,復(fù)雜度為O(n),因為涉及到數(shù)組中元素的移動,這一操作非常耗時,由此可見ArrayList不適合插入和刪除操作。

三、ArrayList與Vector的區(qū)別

現(xiàn)在Vector已經(jīng)很少有人用了,這里只是簡單的記錄下二者區(qū)別:

1、ArrayList線程不安全,Vector是線程安全的

通過Vector源碼我們可以知道很多方法都是加了synchronized關(guān)鍵字,所以Vector是線程安全的。

2、ArrayList創(chuàng)建的默認(rèn)大小為0,Vector創(chuàng)建時的默認(rèn)大小是10。

3、ArrayList 每次擴(kuò)容都以當(dāng)前數(shù)組大小的 1.5 倍去擴(kuò)容, Vector 每次擴(kuò)容都以當(dāng)前數(shù)組大小的 2 倍去擴(kuò)容。當(dāng)指定了 capacityIncrement 之 后,每次擴(kuò)容僅在原先基礎(chǔ)上增加 capacityIncrement 個單位空間。

補(bǔ)充知識:ArrayList詳解,底層是數(shù)組,實現(xiàn)Serializable接口

一、對于ArrayList需要掌握的七點內(nèi)容

ArrayList的創(chuàng)建:即構(gòu)造器

往ArrayList中添加對象:即add(E)方法

獲取ArrayList中的單個對象:即get(int index)方法

刪除ArrayList中的對象:即remove(E)方法

遍歷ArrayList中的對象:即iterator,在實際中更常用的是增強(qiáng)型的for循環(huán)去做遍歷

判斷對象是否存在于ArrayList中:contain(E)

ArrayList中對象的排序:主要取決于所采取的排序算法(以后講)

二、源碼分析

2.1、ArrayList的創(chuàng)建(常見的兩種方式)

List<String> strList = new ArrayList<String>();

List<String> strList2 = new ArrayList<String>(2);

ArrayList源代碼:

基本屬性:

?
1
2
3
4
//對象數(shù)組:ArrayList的底層數(shù)據(jù)結(jié)構(gòu)
private transient Object[] elementData;
//elementData中已存放的元素的個數(shù),注意:不是elementData的容量
private int size;

注意:

transient關(guān)鍵字的作用:在采用Java默認(rèn)的序列化機(jī)制的時候,被該關(guān)鍵字修飾的屬性不會被序列化。

ArrayList類實現(xiàn)了java.io.Serializable接口,即采用了Java默認(rèn)的序列化機(jī)制

上面的elementData屬性采用了transient來修飾,表明其不使用Java默認(rèn)的序列化機(jī)制來實例化,但是該屬性是ArrayList的底層數(shù)據(jù)結(jié)構(gòu),在網(wǎng)絡(luò)傳輸中一定需要將其序列化,之后使用的時候還需要反序列化,那不采用Java默認(rèn)的序列化機(jī)制,那采用什么呢?直接翻到源碼的最下邊有兩個方法,發(fā)現(xiàn)ArrayList自己實現(xiàn)了序列化和反序列化的方法

View Code

構(gòu)造器:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 創(chuàng)建一個容量為initialCapacity的空的(size==0)對象數(shù)組
*/
public ArrayList(int initialCapacity) {
super();//即父類protected AbstractList() {}
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity:" + initialCapacity);
this.elementData = new Object[initialCapacity];
}
 
/**
* 默認(rèn)初始化一個容量為10的對象數(shù)組
*/
public ArrayList() {
this(10);//即上邊的public ArrayList(int initialCapacity){}構(gòu)造器
}

在我們執(zhí)行new ArrayList<String>()時,會調(diào)用上邊的無參構(gòu)造器,創(chuàng)造一個容量為10的對象數(shù)組。

在我們執(zhí)行new ArrayList<String>(2)時,會調(diào)用上邊的public ArrayList(int initialCapacity),創(chuàng)造一個容量為2的對象數(shù)組。

注意:

上邊有參構(gòu)造器的super()方法是ArrayList父類AbstractList的構(gòu)造方法,這個構(gòu)造方法如下,是一個空構(gòu)造方法:

?
1
2
protected AbstractList() {
}

在實際使用中,如果我們能對所需的ArrayList的大小進(jìn)行判斷,有兩個好處:

節(jié)省內(nèi)存空間(eg.我們只需要放置兩個元素到數(shù)組,new ArrayList<String>(2))

避免數(shù)組擴(kuò)容(下邊會講)引起的效率下降(eg.我們只需要放置大約37個元素到數(shù)組,new ArrayList<String>(40))

2.2、往ArrayList中添加對象(常見的兩個方法add(E)和addAll(Collection<? extends E> c))

以上這篇聊一聊jdk1.8中的ArrayList 底層數(shù)組是如何擴(kuò)容的就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/jerry11112/article/details/106951235

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 天堂俺去俺来也www久久婷婷 | 亚洲精品在线播放视频 | 99亚洲国产精品 | 性视频一区二区 | 国产亚洲欧美一区二区 | 一区二区三区精品视频 | 欧美国产视频 | 日韩精品一区在线 | 亚洲精品无码专区在线播放 | 91视频免费网站 | 人妖一区| 日韩精品一区二区三区在线观看 | 久久免费电影 | 久久精品噜噜噜成人av农村 | 国产一级片 | 亚洲精彩视频在线 | 国产黄色小视频 | 国产精品久久久久久久久久久久久久 | 亚洲国产精品成人 | 亚洲天堂久久 | 亚洲 欧美 日韩在线 | 一本大的之伊人 | 国产成人欧美一区二区三区的 | 91中文字幕 | 亚洲一卡二卡 | 欧美成年黄网站色视频 | 一级片在线播放 | 国产一区不卡视频 | 最近2019中文字幕大全视频10 | 国产专区在线 | 日韩三级高清 | 日本激情综合网 | 亚洲成av人影片在线观看 | 亚洲一区二区三区四区的 | 亚洲精品久久久久久久久久久久久 | 亚洲成av人影片在线观看 | 最近的中文字幕在线看视频 | 亚洲在线 | 欧美日韩高清在线一区 | 国产乱淫精品一区二区三区毛片 | 自拍在线 |