激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - Java教程 - Java源碼解析ArrayList及ConcurrentModificationException

Java源碼解析ArrayList及ConcurrentModificationException

2021-06-28 10:45李燦輝 Java教程

今天小編就為大家分享一篇關于Java源碼解析ArrayList及ConcurrentModificationException,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧

本文基于jdk1.8來分析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
/**
 * default initial capacity.
 **/
private static final int default_capacity = 10;
/**
 * shared empty array instance used for empty instances.
 **/
private static final object[] empty_elementdata = {};
/**
 * shared empty array instance used for default sized empty instances. we
 * distinguish this from empty_elementdata to know how much to inflate when
 * first element is added.
 **/
private static final object[] defaultcapacity_empty_elementdata = {};
/**
 * the array buffer into which the elements of the arraylist are stored.
 * the capacity of the arraylist is the length of this array buffer. any
 * empty arraylist with elementdata == defaultcapacity_empty_elementdata
 * will be expanded to default_capacity when the first element is added.
 **/
transient object[] elementdata; // non-private to simplify nested class access
/**
 * the size of the arraylist (the number of elements it contains).
 *
 * @serial
 **/
private int size;

其中初始大小為10,size表示集合中元素的個數。此外,還有兩個空數組empty_elementdata,和defaultcapacity_empty_elementdata。通過defaultcapacity_empty_elementdata的注釋,我們可以了解到,這個變量區別于empty_elementdata,主要是為了決定第一個元素插入時,擴容多大的問題。從這里的描述可以理解到,arraylist創建好后,其實并沒有真正分配數組空間,而是在第一個元素插入時,才分配的空間。這一點是區別于jdk1.6的。在jdk1.6中,arraylist一創建,數據空間就默認分配好了,10個或指定的空間。jdk1.8這么做,可以做到空間延遲分配,提高程序性能。

接下來看一下構造函數。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
   * constructs an empty list with an initial capacity of ten.
   **/
  public arraylist() {
    this.elementdata = defaultcapacity_empty_elementdata;
  }
/**
   * constructs an empty list with the specified initial capacity.
   *
   * @param initialcapacity the initial capacity of the list
   * @throws illegalargumentexception if the specified initial capacity
   *     is negative
   **/
  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);
    }
  }

無參構造函數,將創建一個長度為0的空數組。

有參構造函數,參數大于0時正常創建數組,參數為0時,也是創建長度為0的數組。但它和無參構造函數創建的空數組是可以區別開的,它們使用了不同的對象。

接下來是插入元素add。

?
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
/**
   * appends the specified element to the end of this list.
   *
   * @param e element to be appended to this list
   * @return <tt>true</tt> (as specified by {@link collection#add})
   **/
  public boolean add(e e) {
    ensurecapacityinternal(size + 1); // increments modcount!!
    elementdata[size++] = e;
    return true;
  }
 private void ensurecapacityinternal(int mincapacity) {
    ensureexplicitcapacity(calculatecapacity(elementdata, mincapacity));
  }
 private static int calculatecapacity(object[] elementdata, int mincapacity) {
    if (elementdata == defaultcapacity_empty_elementdata) {
      return math.max(default_capacity, mincapacity);
    }
    return mincapacity;
  }
 private void ensureexplicitcapacity(int mincapacity) {
    modcount++;
    // overflow-conscious code
    if (mincapacity - elementdata.length > 0)
      grow(mincapacity);
  }

通過calculatecapacity函數,我們可以知道,如果是用new arraylist()創建的list,第一次add元素,計算得mincapacity = 1。如果是new arraylist(0)創建的list,計算得mincapacity = 10. 然后再根據mincapacity去grow。

get方法比較簡單,這里不再分析。

arraylist的一個常見問題是concurrentmodificationexception,同步修改異常,也稱為快速失敗,fast-fail。當我們以foreach方式遍歷arraylist時,如果在遍歷過程中刪除arraylist的元素,或者別的線程往arraylist中添加元素,就會拋出該異常。這里需要注意,以for(int i = 0; i < list.size(); i++)的方式遍歷arraylist時,是不會拋出同步修改異常的,但用這種方式遍歷,需要處理好i的前進速度。

那么,用foreach方式遍歷arraylist為什么會拋出同步修改異常呢?

foreach代碼的底層實現,是用iterator對arraylist進行遍歷,在遍歷過程中,會持續調用next獲取下一個元素。next方法中,會首先checkforcomodification(),它的作用是檢查modcount和expectedmodcount是否相等。不相等時,則拋出同步修改異常。那么什么情況下修改次數和期望修改次數不相等呢?這里需要首先弄明白,modcount和expectedmodcount是什么東西?modcount是arraylist從它的父類繼承來的屬性,記錄了集合的修改次數,add,remove時都會給modcount加1. expectedmodcount是迭代器的成員變量,它是在創建迭代器時,取的modcount的值,并且,在遍歷過程中不再改變。那么就清楚了,expectedmodcount其實是開始遍歷時modcount的值,如果在遍歷過程中,arraylist進行了add或remove操作,那么必然導致expectedmodcount和modcount不相等,于是就拋出了同步修改異常。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public e next() {
  checkforcomodification();
  int i = cursor;
  if (i >= size)
    throw new nosuchelementexception();
  object[] elementdata = arraylist.this.elementdata;
  if (i >= elementdata.length)
    throw new concurrentmodificationexception();
  cursor = i + 1;
  return (e) elementdata[lastret = i];
}
final void checkforcomodification() {
  if (modcount != expectedmodcount)
    throw new concurrentmodificationexception();
}

那么,同步修改異常如何避免呢?或者說,我們如何遍歷集合并把其中的某些元素刪除呢?

答案是使用迭代器的remove方法刪除元素。在迭代器的remove方法中,刪除元素后,會重新把modcount賦值給expectedmodcount,所以,它不會拋出同步修改異常。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public void remove() {
     if (lastret < 0)
       throw new illegalstateexception();
     checkforcomodification();
     try {
       arraylist.this.remove(lastret);
       cursor = lastret;
       lastret = -1;
       expectedmodcount = modcount;
     } catch (indexoutofboundsexception ex) {
       throw new concurrentmodificationexception();
     }
   }

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。如果你想了解更多相關內容請查看下面相關鏈接

原文鏈接:https://blog.csdn.net/li_canhui/article/details/85001591

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25
主站蜘蛛池模板: 男男啪羞羞视频网站 | av在线播放网址 | 国产午夜精品一区二区三区四区 | av国产免费 | av在线播放免费 | www日韩在线观看 | 天天干导航 | 玩偶姐姐 在线观看 | 成人福利免费在线观看 | 久久国产精品99久久人人澡 | 黄色特级| 视频一区二区三区在线播放 | 青草av.久久免费一区 | 亚洲最大av网站 | 国产 一区| 久久精品视频69 | 在线观看免费av网 | 亚洲成人欧美在线 | 艹男人的日日夜夜 | 一区二区三区四区精品 | 久久99精品国产99久久6男男 | 精品久久久久久久久中文字幕 | 男女牲高爱潮免费视频男女 | 成人资源在线观看 | 成人在线视频一区 | 日本在线国产 | 国产一区视频观看 | 成人在线视频在线观看 | 欧美a∨一区二区三区久久黄 | 91免费在线视频 | 欧美特一级 | av色先锋| 国产一区二区二 | 国产一级做a爱片在线看免 日日草夜夜 | 中国毛片在线观看 | japanese xxxxhd | 一级大黄毛片 | 日本网站一区二区三区 | 国产成人在线观看免费网站 | 国产日韩在线观看一区 | 91a在线观看 |