日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么?

發布時間:2024/7/23 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者:陌北有棵樹,玩Java,架構師社區合伙人!

【一】關于擴容

如果沒有指定初始容量,則設置為10

/**
?*?Default?initial?capacity.
?*/
private?static?final?int?DEFAULT_CAPACITY?=?10;

ArrayList的擴容比較簡單,容量擴為之前的1.5倍
/**
?*?Increases?the?capacity?to?ensure?that?it?can?hold?at?least?the
?*?number?of?elements?specified?by?the?minimum?capacity?argument.
?*
?*?@param?minCapacity?the?desired?minimum?capacity
?*/
private?void?grow(int?minCapacity)?{
????//?overflow-conscious?code
????int?oldCapacity?=?elementData.length;
????int?newCapacity?=?oldCapacity?+?(oldCapacity?>>?1);
????if?(newCapacity?-?minCapacity?0)
????????newCapacity?=?minCapacity;
????if?(newCapacity?-?MAX_ARRAY_SIZE?>?0)
????????newCapacity?=?hugeCapacity(minCapacity);
????//?minCapacity?is?usually?close?to?size,?so?this?is?a?win:
????elementData?=?Arrays.copyOf(elementData,?newCapacity);
}

【二】關于拷貝

源碼中用到的數組復制的兩個方法分別是:System.arraycopy()和Arrays.copyOf()

一句話總結二者區別:Arrays.copyOf()可以看做是受限制的System.arraycopy()

Arrays.copyOf()是系統自己創建一個數組,再調用System.arraycopy()復制

public?static??T[]?copyOf(U[]?original,?int?newLength,?Class?extends?T[]>?newType)?{@SuppressWarnings("unchecked")
????T[]?copy?=?((Object)newType?==?(Object)Object[].class)
??????????(T[])?new?Object[newLength]
????????:?(T[])?Array.newInstance(newType.getComponentType(),?newLength);
????System.arraycopy(original,?0,?copy,?0,
?????????????????????Math.min(original.length,?newLength));return?copy;
}

System.arraycopy()需要傳入一個目標數組作為參數,同時可以指定拷貝的起點和拷貝的長度

public?static?native?void?arraycopy(Object?src,??int??srcPos,
????????????????????????????????????Object?dest,?int?destPos,int?length);

各個參數的含義:

src - 源數組。
srcPos - 源數組中的起始位置。
dest - 目標數組。
destPos - 目標數據中的起始位置。
length - 要復制的數組元素的數量。

同時要注意的是,上述兩個拷貝方法都是淺拷貝,關于深拷貝和淺拷貝,后續會做詳細說明。

【三】關于Fail-Fast

Fail-Fast是非線程安全的集合,實現的一種錯誤機制。但不能百分百得到保證,只是盡最大努力拋出ConcurrentModificationException。

什么時候產生Fail-Fast
ArrayList中如何實現Fail-Fast
兩個變量:modCount和expectedModCount
只要涉及到數組個數改變的方法,都會導致modCount的改變(add、remove、clear)
當發現expectedModCount和modCount不一致,就會拋出ConcurrentModificationException
所以,Iterator在遍歷時,是不允許被迭代的對象被改變的

final?void?checkForComodification()?{
????if?(modCount?!=?expectedModCount)
????????throw?new?ConcurrentModificationException();
}

如何避免Fail-Fast:用CopyOnWriteArrayList代替ArrayList

【四】關于ArrayList中刪除元素

錯誤的刪除方式一:for循環遍歷刪除

public?void?testRemove()?{
???List?integers?=?new?ArrayList<>(5);
???integers.add(1);
???integers.add(2);
???integers.add(2);
???integers.add(4);
???integers.add(5);for?(int?i?=?0;?i???????if?(integers.get(i)?%?2?==?0)?{
?????????integers.remove(i);
??????}
???}
???System.out.println(integers);
}

這段代碼的輸出是 [1,2,5]

因為在remove方法執行的時候,刪除第一個“2”,會更新后面的索引值,數組變為[1,2,4,5],這樣會導致第二個“2”不會被刪除

錯誤的刪除方式二:使用Iterator遍歷,但仍用ArrayList的remove方法

public?void?testRemove(){
???List?strings?=?new?ArrayList<>();
???strings.add("a");
???strings.add("b");
???strings.add("c");
???strings.add("d");
???Iterator?iterator?=?strings.iterator();while?(iterator.hasNext()){
??????String?next?=?iterator.next();
??????strings.remove(next);
???}
???System.out.println(strings);
}

會拋出ConcurrentModificationException,參見上述的Fail-Fast機制

正確的刪除方法:使用Iterator的remove方法

public?static?void?main(String[]?args)?{
???List?intList?=?new?ArrayList();
???Collections.addAll(intList,?1,?2,?3,?5,?6);
???Iterator?it?=?intList.iterator();while(it.hasNext())?{
??????Integer?value?=?it.next();if(value?==?3?||?value?==?5)?{
?????????it.remove();
??????}
???}
???System.out.println(intList);
}

長按訂閱更多精彩▼

如有收獲,點個在看,誠摯感謝

總結

以上是生活随笔為你收集整理的arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。