一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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

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

Java源碼解析ArrayList及ConcurrentModificationException

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

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

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

接下來看一下構(gòu)造函數(shù)。

?
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);
    }
  }

無參構(gòu)造函數(shù),將創(chuàng)建一個長度為0的空數(shù)組。

有參構(gòu)造函數(shù),參數(shù)大于0時正常創(chuàng)建數(shù)組,參數(shù)為0時,也是創(chuàng)建長度為0的數(shù)組。但它和無參構(gòu)造函數(shù)創(chuàng)建的空數(shù)組是可以區(qū)別開的,它們使用了不同的對象。

接下來是插入元素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函數(shù),我們可以知道,如果是用new arraylist()創(chuàng)建的list,第一次add元素,計算得mincapacity = 1。如果是new arraylist(0)創(chuàng)建的list,計算得mincapacity = 10. 然后再根據(jù)mincapacity去grow。

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

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

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

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

那么,同步修改異常如何避免呢?或者說,我們?nèi)绾伪闅v集合并把其中的某些元素刪除呢?

答案是使用迭代器的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();
     }
   }

總結(jié)

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚州精品永久观看视频 | www.青青草原 | 国产亚洲精品久久yy5099 | 扒开双腿疯狂进出爽爽动态图 | 99热在线精品播放 | 国内亚州视频在线观看 | 草草国产成人免费视频 | 亚洲国产成人超福利久久精品 | chinese老太grandma| 亚洲男人天堂网站 | 亚洲精品成人456在线播放 | 国产美女做爰免费视频软件 | 亚洲天堂精品在线 | 国产精品日韩欧美一区二区 | 精品无码乱码AV | 果冻传媒在线免费观看 | 欧美折磨另类系列sm | 3p文两男一女办公室高h | 欧美成人福利视频 | 趴好撅高打屁股sp调教h | 美女69xx| 久久精品中文字幕 | 乖女的嫩奶水h文孕妇 | 香蕉国产人午夜视频在线 | 国产精品原创永久在线观看 | 奇米视频7777| 久久香蕉国产免费天天 | 久草在在线免视频在线观看 | 波多野结衣之高校教师 | 第一福利在线观看永久视频 | 污斗罗大陆 | 精品视频在线观看 | 亚洲国内精品久久 | 99热这里有精品 | 法国女佣系列在线播放 | 2019午夜福合集高清完整版 | 男女乱淫真视频播放网站 | 男人香蕉好大好爽视频 | 九9热这里真品 | 精品视频在线观看 | 调教催眠 |