日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java ArrayList使用總結

瀏覽:30日期:2022-08-15 08:53:05

提起ArrayList,相信很多小伙伴都用過,而且還不少用。但在幾年之前,我在一場面試中,面試官要求說出ArrayList的擴容機制。很顯然,那個時候的我并沒有關注這些,從而錯過了一次機會。不過好在我還算比較喜歡搞事情的,所以今天這篇文章也算是填坑吧??赐赀@邊文章你將了解到:

ArrayList底層實現 ArrayList為什么允許null值 ArrayList為什么可重復 ArrayList查詢效率和插入效率對比 類圖

下圖是ArrayList的類圖結構

Java ArrayList使用總結

ArrayList繼承于 AbstractList,實現了 List, RandomAccess, Cloneable, java.io.Serializable 這些接口。這里逐個分析一下這里接口的意義:

RandomAccess是一個標志接口,表明實現這個這個接口的 List集合是支持快速隨機訪問的。有興趣可以看看Collections類中哪個方法用到了這個標志性接口。 實現 Cloneable接口并覆蓋了方法clone(),能被克隆。 實現了java.io.Serializable 接口,這意味著ArrayList支持序列化,能通過序列化去傳輸(請注意,ArrayList的序列化是有點小特殊的,后面會講解)。 源碼解析

成員變量在正式進入源碼分析之前,我們有必要先看看它的成員變量都有哪些,這里列舉比較重要的成員變量:

private int size; // 實際元素個數transient Object[] elementData; //真正保存元素的數組private static final int DEFAULT_CAPACITY = 10;//默認的初始容量大小

構造方法我們有三種初始化辦法:無參數直接初始化、指定大小初始化、指定初始數據初始化,源碼如下:

//1、無參數直接初始化,數組大小為空public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}//2、指定初始數據初始化public ArrayList(Collection<? extends E> c){ //elementData是保存數組的容器,默認為null elementData=c.toArray(); //如果給定的集合(c)數據有值 if((size=elementData.length)!=0){ //c.toArray might(incorrectly)not return Object[](see 6260652) //如果集合元素類型不是Object類型,我們會轉成Object if(elementData.getClass()!=Object[].class){ elementData=Arrays.copyOf(elementData,size,Object].class); } }else{ //給定集合(c)無值,則默認空數組 this.elementData=EMPTY_ELEMENTDATA }}//3、指定初始容量public ArrayList(int initialCapacity) {//指定的初始容量大于0,將elementData初始化為指定大小的數組 if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { //否則初始化成一個空數組 this.elementData = EMPTY_ELEMENTDATA; }}

除過源碼中注釋外,補充幾點:

ArrayList無參構造器初始化時,默認大小是空數組,并不是大家常說的10,10是在第一次add的時候擴容的數組值。 使用方式二進行創建對象時,如果入參容器保存的對象不是Object,則轉換為Object。

DEFAULTCAPACITY_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA又是什么鬼?它其實是定義在成員變量的兩個空數組,

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};private static final Object[] EMPTY_ELEMENTDATA = {};

很明顯問題來了,既然都是空數組,為什么要聲明兩個?一個不行嗎?讀者請先思考一下,帶著疑問往下看。

新增和擴容實現

通過構造方法可以很清楚的看到,ArrayList的確是基于數組的,但動態又從何說起?新增時就是給數組中添加元素,主要分為兩步走:

判斷是否需要擴容,如果需要擴容執行擴容操作; 直接賦值。

對應源碼如下:

public boolean add(E e) {//確保數組大小是否足夠,不夠執行擴容,size為當前數組元素個數,判斷size+1是因為后面還要size++ ensureCapacityInternal(size + 1); //1 elementData[size++] = e;//2 return true;}

我們先來看一下擴容部分的源碼:

private void ensureCapacityInternal(int minCapacity) {//先調用calculateCapacity計算容量 ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}private static int calculateCapacity(Object[] elementData, int minCapacity) { //如果當前數組還是個空數組,也就是他用過無參構造去初始化的 //那么直接返回DEFAULT_CAPACITY,即10 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity;}private void ensureExplicitCapacity(int minCapacity) { modCount++; // 如果當前容量已經大于當前數組的長度了,說明需要去擴容了 if (minCapacity - elementData.length > 0) //擴容 grow(minCapacity);}private void grow(int minCapacity){ int oldCapacity = elementData.length; //oldCapacity>>1是把oldCapacity除以2的意思 int newCapacity=oldCapacity+(oldCapacity>>1); //如果擴容后的值<我們的期望值,擴容后的值就等于我們的期望值 if(newCapacity-minCapacity<0) newCapacity = minCapacity; //如果擴容后的值>jvm所能分配的數組的最大值,那么就用Integer的最大值 if(newCapacity-MAX_ARRAY_SIZE>0) elementData=Arrays.copyOf(elementData,newCapacity);}

注釋相對來說已經比較詳細了,這里需要注意以下幾點:

上面有個問題是為什么需要聲明兩個空數組。我們在看到上面源碼的時候有一個方法為calculateCapacity,這個方法內部邏輯只有在通過無參構造初始化ArrayList的時候才會改變將要返回的minCapacity。而返回的這個值將會決定下面的數組是否需要擴容。如果我們通過指定大小的方式初始化ArrayList并指定大小為0,這說明我們需要的就是一個空的ArrayList,不需要去擴容,你細品; 新增時,沒有對值進行校驗,所以新增值可以為null,且沒有做重復值判斷,所以元素可以重復; ArrayList中的數組的最大值是Integer.MAX_VALUE,超過這個值,JVM就不會給數組分配內存空間了; 擴容是原來容量大小+容量大小的一半,簡單說就是擴容后的大小是原來容量的1.5倍。

擴容完成之后,就是簡單的賦值了,賦值時并沒有加鎖,所以是線程不安全的。

擴容的本質

在grow方法的最后,擴容是通過Arrays.copyOf(elementData,newCapacity);這行代碼實現的。這個方法實際上調用的方法是我們經常使用的System.arraycopy:

/***@param src 被拷貝的數組*@param srcPos 從數組那里開始*@param dest 目標數組*@param destPos從目標數組那個索引位置開始拷貝*@param length 拷貝的長度*此方法是沒有返回值的,通過dest的引用進行傳值*/public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length);

這個方法是一個native方法,雖然不能看到方法內部的具體實現,但通過參數也可以管中窺豹。這個方法會移動元素。所以說數組如果要擴容,需要重新分配一塊更大的空間,再把數據全部復制過去,時間復雜度 O(N);而且你如果想在數組中間進行插入和刪除,每次必須搬移后面的所有數據以保持連續,時間復雜度 O(N)。由于數組又是一塊連續的內存空間,能夠根據索引快速訪問元素。上面也就解釋了一開始那個問題:ArrayList為什么插入慢,查詢快。

刪除

ArrayList有多種刪除方法,這里以根據值刪除的方式進行說明(其他原理類似):

public boolean remove(Object o) { //如果要刪除的值是null,刪除第一個是null的值 if(o==null){ for(int index=0;index<size;index++) if(elementData[index]==null){ fastRemove(index) return true; } }else{ //如果要刪除的值不為null,找到第一個和要刪除的值相等的刪除 for(int index=0;index<size;index++) //這里是根據 equals來判斷值相等的,相等后再根據索引位置進行刪除 //所以根據對象刪除時,一般來說,如果你確定要刪除的是某一類的業務對象,則需要重寫equals if(o.equals(elementData[index]){ fastRemove(index) return true; } } return false}

核心其實是fastRemove方法:

private void fastRemove(int index){ //記錄數組的結構要發生變動了 nodCount++; //numMoved表示刪除index位置的元素后,需要從index后移動多少個元素到前面去 //減1的原因,是因為size從1開始算起,index從0開始算起 int numMoved=size-index-1; if(numMoved>0) //從index+1位置開始被拷貝,拷貝的起始位置是index,長度是numMoved System.arraycopy(elementData, index+1, elementData, index, numMoved); //數組最后一個位置賦值null,幫助GC(沒有引用則自動回收了) elementData[--size] = null;}

從源碼中,我們可以看出,某一個元素被刪除后,為了維護數組結構,我們都會把數組后面的元素往前移動,同時釋放最后一個引用,便于回收。

總結

本文主要從ArrayList的源碼入手,分別從初始化、新增、擴容、刪除四個方面展開學習。我們發現ArrayList內部其實就是圍繞了一個數組,在數組容量不足時將數組擴容至更大,所以也就自然被稱作基于動態數組。微信搜索Java成神之路或掃描下方二維碼,發現更多Java有趣知識,讓我們一起成長!

以上就是Java ArrayList使用總結的詳細內容,更多關于Java ArrayList使用的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
999久久久亚洲| 激情综合网站| 亚洲精品极品| 欧美综合国产| 在线免费观看亚洲| 免费日韩av| 欧美精品一区二区三区精品| 国产999精品在线观看 | 91大神在线观看线路一区| 日本视频中文字幕一区二区三区| 最新国产精品| 国产福利亚洲| 久久精品官网| 亚洲一区二区三区四区电影| 日本aⅴ亚洲精品中文乱码| 久久不卡国产精品一区二区| 日韩在线第七页| 久久亚洲视频| 久久99蜜桃| av日韩中文| 国产视频一区在线观看一区免费| 亚洲精品欧美| 国产精品一国产精品k频道56| 久久精品国产精品亚洲毛片| 涩涩av在线| 国产视频一区免费看| 日韩高清在线一区| 色综合狠狠操| 蜜臀va亚洲va欧美va天堂| 国产视频一区二| 日韩成人三级| 亚洲免费福利一区| 国产精品二区不卡| 亚洲综合精品| 国产一区调教| 在线看片一区| 成人日韩精品| 日本一区二区三区视频在线看| 激情综合婷婷| 蜜桃av一区二区| 成人影视亚洲图片在线| 欧美女激情福利| 国产精品久久久久久模特 | 91精品1区| 国产麻豆精品久久| 午夜国产一区二区| 蜜桃久久久久| 亚洲少妇一区| 国产aⅴ精品一区二区三区久久| 午夜在线一区二区| 国产成人免费| 免费不卡在线视频| 亚洲电影有码| 免费在线观看一区| 视频精品一区| 欧美午夜不卡| 深夜福利视频一区二区| 国产精品亚洲人成在99www | 粉嫩av一区二区三区四区五区| 国产精品7m凸凹视频分类| 美女视频黄免费的久久| 中文无码久久精品| 国产伊人精品| 国产夫妻在线| 欧美伊人久久| 免费久久99精品国产自在现线| 亚洲成人不卡| 岛国av免费在线观看| 你懂的国产精品| 欧美一级一区| 日韩av中文字幕一区二区| 国产亚洲精品v| 神马午夜久久| 日韩免费在线| 成人亚洲一区| 成人在线免费观看91| 久久精品99国产国产精| 中文字幕av一区二区三区人| 欧美大黑bbbbbbbbb在线| 国精品产品一区| 欧美国产极品| 国产亚洲高清一区| 日韩中文字幕麻豆| 激情综合网站| 免费视频一区三区| 成人羞羞视频播放网站| 中文在线中文资源| 伊人久久在线| 欧美sm一区| 视频一区中文| 女同性一区二区三区人了人一| 视频福利一区| 国内亚洲精品| 国产综合精品一区| 欧美肉体xxxx裸体137大胆| 亚洲一级少妇| 99精品在线| 欧美日韩国产精品一区二区亚洲| 亚洲激情av| 欧美天堂在线| 国产精品mm| 久久这里只有| 在线看片福利| 91精品国产乱码久久久久久久 | 国产精品亚洲欧美| 欧美激情精品| 成人一区而且| 日韩成人高清| 亚洲午夜av| 婷婷亚洲五月色综合| 乱人伦精品视频在线观看| 最新亚洲激情| 亚洲3区在线| 国产精品99久久免费| 国语对白精品一区二区| 欧美天堂视频| 99久久久久国产精品| 亚洲国产一区二区三区在线播放| 欧美日韩国产在线一区| 亚洲图片久久| 国产精品美女在线观看直播| 91麻豆国产自产在线观看亚洲| 日韩高清中文字幕一区二区| 99精品网站| 老色鬼久久亚洲一区二区| 婷婷精品在线| 激情中国色综合| 日韩午夜在线| 日韩国产欧美视频| 丁香婷婷久久| 亚洲少妇诱惑| 久久av中文| 亚洲成人免费| 国产精品成人国产| 久久精品免费一区二区三区| 首页国产欧美日韩丝袜| 三级亚洲高清视频| 欧美交a欧美精品喷水| 日韩中文影院| 日本午夜精品一区二区三区电影| 国产精品二区不卡| 蜜臀va亚洲va欧美va天堂| 国产精品一级在线观看| 日韩中文在线电影| 亚洲三级av| 日韩免费久久| 91成人福利| 国产综合精品| 国产精品22p| 在线视频精品| 麻豆精品视频在线观看免费| 精品1区2区3区4区| 久久精品欧洲| 久久99伊人| 高清一区二区三区av| 视频一区二区三区在线| 国产va在线视频| 日韩在线观看一区二区三区| 日韩欧美国产精品综合嫩v| 日韩精品亚洲一区二区三区免费| 欧美13videosex性极品| 国产欧美日韩精品一区二区三区| 国精品一区二区| 国产一区二区亚洲| 日韩国产精品久久久| 中国女人久久久| 日韩和的一区二在线| 日韩二区三区四区| 久久婷婷亚洲| 美女在线视频一区| 亚洲va久久久噜噜噜久久| 久久精品国产大片免费观看| 国产精品s色| 日韩一区网站| 国产精品日本| 秋霞国产精品| 久久久免费人体| 日韩午夜视频在线| 亚洲欧美日韩专区| 久久男女视频| 91欧美在线| 国产免费av一区二区三区| 蜜臀av在线播放一区二区三区| 日韩中文在线电影| 国产一区精品福利| 国产精选久久| 91成人福利| 欧美日韩黄网站| 日韩精品一页| 亚洲精品国产精品粉嫩| 中文日韩在线| 亚洲一区欧美二区| 久久精品国产www456c0m| 国产美女高潮在线观看| 精品一区二区三区中文字幕在线| 国产日韩中文在线中文字幕 | 视频一区欧美日韩| 亚洲综合电影一区二区三区| 欧美精品一区二区久久| 欧美/亚洲一区|