91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中ArrayList怎么用

發布時間:2021-11-24 17:38:36 來源:億速云 閱讀:244 作者:小新 欄目:大數據

小編給大家分享一下java中ArrayList怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

ArrayList構造器簡介

在java中,一切皆對象,一切操作又離不開對象,ArrayList也是如此,所以想要研究ArrayList是如何工作的就要從ArrayList的構造開始。

ArrayList提供了三個構造,分別是不帶任何參數的構造器、接受一個int類型值的構造器和接受一個帶泛型的Collection的構造器,首先我們從最簡單的沒有任何參數、也是大多數人最常用的這個構造器開始。

無參數構造器

打開源碼可以看到無參數構造器非常的簡單,只有一行代碼,代碼如下:

java中ArrayList怎么用

其中DEFAULTCAPACITY_EMPTY_ELEMENTDATA是ArrayList中定義的一個靜態的不可變的空數組,而elementData則是ArrayList保存實際數據使用的數組引用,也就是說如果用默認無參數構造器構造ArrayList的話是沒有初始數組的(為空,所有實例共享)。

接收一個int類型值的構造器

打開源碼,可以看到如下代碼:

java中ArrayList怎么用

可以看到,當傳入參數為0時與不傳參數的邏輯是一致的,當傳入參數大于0時ArrayList會構建一個與傳入參數為大小的Object數組,而當傳入參數小于0時,就會拋出一個非法參數異常(IllegalArgumentException)了。

接收一個Collection參數的構造器

仍然是打開源碼查看,可以看到以下代碼:

java中ArrayList怎么用

首先是將傳入參數轉換為數組,然后將這個數組引用賦值給ArrayList內部維護的數組引用,如果這個數組的長度是0時你會發現這時的行為又與空參數構造器的行為一致了,而當這個數組長度不是0時,ArrayList做了一些小動作,對于這些小動作,注釋也寫的很清楚了,c.toArray might (incorrectly) not return Object[],也就是說這個數組有可能不是Object類型的數組(在不正確的情況下,這個是由JDK本身的一個BUG造成的,具體的可以去JDK的BUG庫http://bugs.java.com/bugdatabase/中查找BUG ID為6260652的BUG,有興趣的同學可以自行查找閱讀,本文不去詳細介紹),所以為了保證代碼的健壯性,就加了這么一個類型檢查,而為什么要檢查這個數組是不是Object類型的呢?這個很簡單,就是因為如果此處引用的是一個String類型的數組,后續如果往里邊放入一個非String類型的數據就會報錯,而這個錯誤通常是到運行時才會發現的。

ArrayList的構造器介紹到此就結束了,下面開始介紹ArrayList的方法,由于篇幅有限,所以本文僅挑選幾個ArrayList初級使用者最常用的方法介紹。

public boolean add(E e)

這個方法是最常用的一個方法,其作用就是將一個新元素加入到當前list的尾部,源碼如下:

java中ArrayList怎么用

可以看到這個方法非常簡潔,調用了另外一個方法ensureCapacityInternal,然后將數據填充進數組,更新size,整個方法就結束了,固定返回的true,也就是該方法只要不拋出異常肯定會返回true,至于ensureCapacityInternal方法會在后面講解,ArrayList中也多次調用到了該方法,算是核心方法之一。可以很容易看出,該方法的漸進時間復雜度為O(1)(不擴容的情況下)。

public void add(int index, E element)

這個方法的作用是將一個元素插入到list的指定位置,源碼如下:

java中ArrayList怎么用

首先是第一行,第一行很簡單,看方法名就知道是范圍檢測,具體的行為就是檢測當前傳入的index參數是否大于當前size或者小于0,如果大于當前size或者小于0的話就拋出一個索引越界異常(IndexOutOfBoundsException),然后該方法也調用了ensureCapacityInternal方法,然后就是將參數index位置和index位置之后的數據給全部后移一位,也就是說該方法插入的位置后邊的數據越多,那么要移位的數據也就越多,效率也就越低。該方法的最壞時間復雜度為O(n)(不擴容的情況下),其中n等于ArrayList的size。

public E remove(int index)

該方法是將指定索引處的數據刪除,源碼如下:

java中ArrayList怎么用

該方法的第一行仍然是范圍檢查,不同的是只要index不是大于等于ArrayList的size就不會拋出異常,但是這一行不拋出異常不代表后邊就不會拋出異常,該處沒有顯示檢查是否小于0是因為后邊第三行有從數組中取數據這個操作,而對于該操作,如果index小于0的話是一定會拋出異常的。然后第四行計算了一下需要移動位置的元素,也就是index位置之后還有多少元素需要前移,當該值大于0時(注:只會大于0或者等于0,不可能小于0),說明有需要移動的元素,將這numMoved個元素統統前移一位,然后將原數組的最后一位設置為null以便于GC可以清除該處引用(注:因為使用的System.arraycopy方法,所以并不會刪除數據,只會復制,而原來數組的最后一位雖然已經復制前移,而且size也已經更新,獲取不到該引用的數據,但是該引用仍然存在,并沒有被清空,所以下次GC的時候如果該處沒有填充新的值覆蓋,那么這個引用將不會被回收并且也獲取不到該處的值,需要詳細了解的可以看一下java的GC原理或者加我Q1213812243詢問^_^)。最后,將第三行獲取到的該位置的數據返回,至此,該方法結束。由于該方法也需要原數組數據的移位,所以很容易可以得出該方法的最壞時間復雜度也是O(n),其中n等于ArrayList的size。

public boolean remove(Object o)

該方法是從ArrayList中刪除指定元素,更準確的說是從ArrayList中刪除第一個與指定元素相同的元素,話不多說上源碼:

java中ArrayList怎么用

由該方法的實現可以看出,如果傳入的元素為null時,該方法將刪除ArrayList中的第一個null元素(不是全部的null元素)并返回true,如果傳入元素不為null時,該方法將調用傳入元素的equals方法與ArrayList中的元素一一對比,直到發現第一個相同的元素,然后刪除并返回true,如果遍歷整個list發現都沒有與傳入對象相同的對象,那么該方法將返回false表示刪除失敗。這里要注意一個小細節,該方法實際刪除元素操作用的是fastRemove而不是上一個提到的public E remove(int index),而根據命名可以猜測出fastRemove方法刪除是比較快的,但是具體是哪兒快了呢?首先查看源碼:

java中ArrayList怎么用

與上一個remove方法對比,很容易可以看出這個方法由于是內部使用的,也不需要返回值,所以并沒有去檢查參數index的范圍合法性,也沒有把要刪除的數據取出,省了這兩個開銷,雖然省的并不多,但是如果在一個大型系統中,這樣的小開銷累計起來也是很大的。同樣的,很容易可以得出該方法的時間漸進復雜度為O(n),其中n等于ArrayList的size。

public E get(int index)

該方法是從ArrayList中取數據,數據存起來的目的就是為了后續的使用,所以該方法是最常用也是最重要的一個方法,源碼如下:

java中ArrayList怎么用

可以看出,該方法很簡單,僅僅檢查了一下參數的范圍,然后就直接取數據返回了,而elementData方法也只有短短的一行

java中ArrayList怎么用

很容易可以得出該方法的時間漸進復雜度為O(1)。

private void ensureCapacityInternal(int minCapacity)

這個方法是前面提及的但是并沒有具體介紹的一個方法,把這個方法放在最后是因為這個方法算是ArrayList的一個核心方法,該方法的作用就是檢查內部數組是否夠用,如果不夠用的話自動擴充,源碼如下:

java中ArrayList怎么用

該方法又調用了ensureExplicitCapacity方法,而ensureExplicitCapacity方法的源碼如下:

java中ArrayList怎么用

該方法判斷了一下參數是否大于當前數組的最大長度,如果大于那么調用grow方法擴容,如果不大于那么不做任何操作。grow方法源碼如下:

java中ArrayList怎么用

該方法也很簡單,只有7行代碼,在第一行首先計算出原數組的長度,然后第二行計算出原數組長度擴充1.5倍后的新的長度(注:右移一位等價于除以2),第三行判斷了擴充1.5倍后的長度是否大于參數(實際需要的長度),如果小于該長度的話將擴充后的新長度更新為參數值(minCapacity),然后在第5行判斷了擴充后的長度是否大于MAX_ARRAY_SIZE這個靜態變量,如果大于該長度的話使用hugeCapacity方法確定是否溢出(即數組長度是否大于Integer.MAX_VALUE),該方法進入后正常情況是肯定會返回Integer.MAX_VALUE,因為外部已經判斷過minCapacity是否大于MAX_ARRAY_SIZE了,只有大于該值才能進來,所以此方法必定返回Integer.MAX_VALUE,ArrayList內部維護的數組長度也達到了最大值Integer.MAX_VALUE,而此時當list再次填充滿需要擴容的時候,傳到此處的參數為(size+1)將是一個負數(Integer溢出),然后調用hugeCapacity方法時會發現傳進來的參數是一個負數,說明已經溢出了,將會拋出一個異常。(注:如果對此處的溢出不理解可以加QQ1213812243詢問或者自行百度)

該方法的最后一行會將數據從老數組遷移至新數組,而老數組由于沒有了引用所以會在后續的GC中被清除。很容易可以得出該方法的時間漸進復雜度為O(n)(需要擴容的情況下,不需要擴容為O(1)),其中n等于當前ArrayList的size。

以上是“java中ArrayList怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

淅川县| 明光市| 南漳县| 土默特右旗| 安福县| 新巴尔虎左旗| 云和县| 讷河市| 临夏市| 资阳市| 肥西县| 正宁县| 漳平市| 汉阴县| 信宜市| 普安县| 望都县| 五原县| 仪征市| 黔江区| 肇州县| 天长市| 旬阳县| 麻城市| 沙坪坝区| 新干县| 通州市| 南京市| 南汇区| 嘉义市| 天津市| 六枝特区| 固始县| 武清区| 遂宁市| 大石桥市| 贡山| 麻城市| 江城| 武冈市| 元江|