成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

實(shí)現(xiàn)一個(gè)ArrayList過程

NickZhou / 1410人閱讀

摘要:構(gòu)造器一個(gè)無參構(gòu)造器一個(gè)參數(shù)為型的有參構(gòu)造器一個(gè)參數(shù)為型的有參構(gòu)造器。參數(shù)為型的構(gòu)造器用來實(shí)現(xiàn)將其他繼承類的容器類轉(zhuǎn)換成。此處僅實(shí)現(xiàn)前兩種。默認(rèn)的大小無參構(gòu)造器中的是定義的私有變量,默認(rèn)值是,用來創(chuàng)建一個(gè)大小為的數(shù)組。

前言

ArrayList,可隨意添加和刪除元素而不許考慮數(shù)組的大小。

構(gòu)造器

一個(gè)無參構(gòu)造器、一個(gè)參數(shù)為int型的有參構(gòu)造器、一個(gè)參數(shù)為Collection型的有參構(gòu)造器。參數(shù)為Collection型的構(gòu)造器用來實(shí)現(xiàn)將其他繼承Collection類的容器類轉(zhuǎn)換成ArrayList。此處僅實(shí)現(xiàn)前兩種。

public ArrayListDemo(){
 this(DEFAULT_CAPACITY);
}
public ArrayListDemo(int size){
 if (size < 0){
  throw new IllegalArgumentException("默認(rèn)的大小" + size);
 }else{
  elementData = new Object[size];
 }
}

無參構(gòu)造器中的DEFAULT_CAPACITY是定義的私有變量,默認(rèn)值是10,用來創(chuàng)建一個(gè)大小為10的數(shù)組。有參構(gòu)造器中,則是通過int參數(shù)來生成指定大小的Object數(shù)組。而可以看到elementData才是真正的用來存儲(chǔ)元素的數(shù)組。

add方法

核心內(nèi)容是往容器中添加元素,add方法有兩個(gè)重載方法,一個(gè)是add(E e),另一個(gè)是add(int index,E e),但是其還要處理動(dòng)態(tài)數(shù)組,即數(shù)組大小不滿足的時(shí)候,擴(kuò)大數(shù)組的內(nèi)存。

public void add(E e){
 isCapacityEnough(size + 1);
 elementData[size++] = e;
}

isCapacityEnough方法用來判斷是否需要擴(kuò)容,傳入的參數(shù)就是最小的擴(kuò)容空間。因?yàn)閍dd一個(gè)元素,所以最小的擴(kuò)容空間,即所有元素+1,這里的size就是真正的元素個(gè)數(shù)。

private void isCapacityEnough(int size){
 if (size > DEFAULT_CAPACITY){
  explicitCapacity(size);
 }
 if (size < 0){
  throw new OutOfMemoryError();
 }
}

判斷需要擴(kuò)容的空間是不是比默認(rèn)的空間大,如果需要的空間比默認(rèn)的空間大,就調(diào)用explicitCapacity繼續(xù)擴(kuò)容,這里有個(gè)size小于0的判斷,出現(xiàn)size小于0主要因?yàn)楫?dāng)size超過Integer.MAX_VALUE就會(huì)變成負(fù)數(shù)。

private final static int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;
private void explicitCapacity(int capacity){
 int newLength = elementData.length * 2;
 if (newLength - capacity < 0){
  newLength = capacity;
 }
 if (newLength > (MAX_ARRAY_LENGTH)){
  newLength = (capacity > MAX_ARRAY_LENGTH ? Integer.MAX_VALUE : MAX_ARRAY_LENGTH);
 }
 elementData = Arrays.copyOf(elementData, newLength);
}

首先,定義一個(gè)數(shù)組最大的容量的常理為最大值,這個(gè)值按照官方的源碼中的解釋是要有些VM保留了數(shù)組的頭部信息在數(shù)組中,因此實(shí)際存放數(shù)據(jù)的大小就是整數(shù)的最大值 - 8.

接著設(shè)定一個(gè)要擴(kuò)容的數(shù)組的大小,雖然上面說了有一個(gè)擴(kuò)容空間的值size+1,這個(gè)是實(shí)際我們最小需要擴(kuò)容的大小。但為了繼續(xù)增加元素,而不頻繁的擴(kuò)容,因此一次性的申請(qǐng)多一些的擴(kuò)容空間。newlength打算申請(qǐng)為數(shù)組長(zhǎng)度的2倍,然后去判斷這個(gè)長(zhǎng)度是否滿足需要的擴(kuò)容空間的值,即有了后續(xù)的兩段代碼

if (newLength - capacity < 0){
 newLength = capacity;
}
if (newLength > (MAX_ARRAY_LENGTH)){
 newLength = (capacity > MAX_ARRAY_LENGTH ? Integer.MAX_VALUE : MAX_ARRAY_LENGTH);
}

如果2倍的長(zhǎng)度仍然不滿足,則申請(qǐng)到需要的擴(kuò)容長(zhǎng)度。在我們只增加一個(gè)元素的情況下,這個(gè)判斷是永遠(yuǎn)不會(huì)生效的,但是如果有addAll方法,則增加的元素很多,就要導(dǎo)致一次申請(qǐng)2倍的長(zhǎng)度是不夠的。第二個(gè)判斷是判斷newLength的長(zhǎng)度如果超過上面定義的數(shù)組最大長(zhǎng)度則判斷要需要的擴(kuò)容空間是否大于數(shù)組最大長(zhǎng)度,如果大于則newLength為 MAX_VALUE ,否則為 MAX_ARRAY_LENGTH。

最后,調(diào)用Arrays.copyOf(elementData, newLength)得到一個(gè)擴(kuò)容后的數(shù)組。

add的另一個(gè)重載方法如下

public void add(int index, E e) {
 //判斷是不是越界
 checkRangeForAdd(index);
 //判斷需不需要擴(kuò)容
 isCapacityEnough(size + 1);
 //將index的元素及以后的元素向后移一位
 System.arraycopy(elementData,index,elementData,index + 1,size - index);
 //將index下標(biāo)的值設(shè)為e
 elementData[index] = e;
 size++;
}
private void checkRangeForAdd(int index){
 //這里index = size是被允許的,即支持頭,中間,尾部插入
 if (index < 0 || index > size){
  throw new IndexOutOfBoundsException("指定的index超過界限");
 }
}
get方法

用來得到容器中指定下標(biāo)的元素

private void checkRange(int index) {
 if (index >= size || index < 0){
  throw new IndexOutOfBoundsException("指定的index超過界限");
 }
}
public E get(int index){
 checkRange(index);
 return (E)elementData[index];
}
indexOf方法

用來得到指定元素的下標(biāo),判斷傳入的元素是否為null,如果為null,則依次與null。如果不為空,則用equals依次比較。匹配成功就返回下標(biāo),匹配失敗就返回-1。

public int indexOf(Object o){
 if (o != null) {
  for (int i = 0 ; i < size ; i++){
   if (elementData[i].equals(0)){
    return i;
   }
  }
 }else {
  for (int i = 0 ; i < size ; i++){
   if (elementData[i] == null) {
    return i;
   }
  }
 }
 return -1;
}
contains方法

用來判斷該容器中是否包含指定的元素。在有了indexOf方法的基礎(chǔ)上,contains的實(shí)現(xiàn)就很簡(jiǎn)單了。

public boolean contains(Object o){
return indexOf(o) >= 0;
}
size方法

用來得到容器類的元素個(gè)數(shù),實(shí)現(xiàn)很簡(jiǎn)單,直接返回size的大小即可。

public int size(){
 return size;
}
isEmpty方法

用來判斷容器是否為空,判斷size方法的返回值是否為0即可。

public boolean isEmpty(){
 return size() == 0;
}
remove方法

用來對(duì)容器類的元素進(jìn)行刪除,與add一樣,remove方法也有兩個(gè)重載方法,分別是remove(Object o)和remove(int index)

public E remove(int index) {
 E value = get(index);
 int moveSize = size - index - 1;
 if (moveSize > 0){
  System.arraycopy(elementData,index + 1, elementData,index,size - index - 1);
 }
 elementData[--size] = null;
 return value;
}
 
public boolean remove(Object o){
 if (contains(o)){
  remove(indexOf(o));
  return true;
 }else {
  return false;
 }
}

第一個(gè)remove方法是核心方法,首先得到要?jiǎng)h除的下標(biāo)元素的值,然后判斷index后面的要前移的元素的個(gè)數(shù),如果個(gè)數(shù)大于零,則調(diào)用庫(kù)方法,將index后面的元素向前移一位。最后elementData[--size] = null;縮減size大小,并將原最后一位置空。

第二個(gè)remove方法不需要向第一個(gè)方法一樣,需要告訴使用者要?jiǎng)h除的下標(biāo)對(duì)應(yīng)的元素,只需要判斷是否刪除成功即可。如果要?jiǎng)h除的元素在列表中,則刪除成功,如果不在則失敗。因此調(diào)用contains方法就可以判斷是否要?jiǎng)h除的元素在列表中。在則調(diào)用remove(int index),不在則返回失敗。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71914.html

相關(guān)文章

  • 數(shù)組和列表的轉(zhuǎn)換問題

    摘要:以下指代數(shù)組,指代數(shù)組列表。常見的轉(zhuǎn)換方法是或。在的使用過程中需要注意,當(dāng)要轉(zhuǎn)換的長(zhǎng)度小于的時(shí),不要試圖通過傳入形參的方式進(jìn)行轉(zhuǎn)換,雖然這在的長(zhǎng)度大于時(shí)不會(huì)出現(xiàn)問題。所以,極度建議在轉(zhuǎn)換之前初始化的長(zhǎng)度為的,并且使用返回值重新給賦值。 Array 和 List 都是我們?cè)陂_發(fā)過程中常見的數(shù)據(jù)結(jié)構(gòu)。我們都知道 Array 是定長(zhǎng)的,List 是可變長(zhǎng)。而且,List 的實(shí)現(xiàn)類 Array...

    ChristmasBoy 評(píng)論0 收藏0
  • Java筆記-容器源碼(持續(xù)更新)

    摘要:加載因子是哈希表在其容量自動(dòng)增加之前可以達(dá)到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時(shí),則要對(duì)該哈希表進(jìn)行操作即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu),從而哈希表將具有大約兩倍的桶數(shù)。成員變量每個(gè)對(duì)由封裝,存在了對(duì)象數(shù)組中。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 LinkedLis...

    mrli2016 評(píng)論0 收藏0
  • Java容器類研究4:ArrayList

    摘要:顯然,開發(fā)人員認(rèn)為通過下標(biāo)遍歷的數(shù)組結(jié)構(gòu)更加高效。在進(jìn)行分裂時(shí),原始保留中部至末尾的元素,新的保留原起始位置到中部的元素。同樣,也會(huì)進(jìn)行重新賦值,使得在使用前與保持一致。在遍歷時(shí),會(huì)調(diào)用方法,將動(dòng)作施加于元素之上。 java.util.ArrayList ArrayList繼承自AbstractList,AbstractList為隨機(jī)訪問數(shù)據(jù)的結(jié)構(gòu),如數(shù)組提供了基本實(shí)現(xiàn),并且提供了It...

    xfee 評(píng)論0 收藏0
  • 深入了解Java集合中的ArrayList

    摘要:實(shí)現(xiàn)了接口,所以包含的基本方法新增,刪除,插入等都實(shí)現(xiàn)了。線程安全問題在多線程情況下有線程進(jìn)行修改時(shí),是線程不安全的。線程安全性問題,取決于如何應(yīng)用。反映的是當(dāng)前數(shù)組中存了多少數(shù)據(jù),而則反映的是內(nèi)部數(shù)組的容量。 什么是ArrayList ArrayList 是一個(gè)可擴(kuò)容數(shù)組Resizable-array,它實(shí)現(xiàn)了List接口的所有方法。 從對(duì)ArrayList的簡(jiǎn)單描述中我們可以得出...

    zeyu 評(píng)論0 收藏0
  • Java集合干貨——ArrayList源碼分析

    摘要:關(guān)于的具體實(shí)現(xiàn),一些基本的都也知道,譬如數(shù)組實(shí)現(xiàn),線程不安全等等,但是更加具體的就很少去了解了,例如初始化的長(zhǎng)度,擴(kuò)容等。 前言 在之前的文章中我們提到過ArrayList,ArrayList可以說是每一個(gè)學(xué)java的人使用最多最熟練的集合了,但是知其然不知其所以然。關(guān)于ArrayList的具體實(shí)現(xiàn),一些基本的都也知道,譬如數(shù)組實(shí)現(xiàn),線程不安全等等,但是更加具體的就很少去了解了,例如:...

    Render 評(píng)論0 收藏0
  • Java集合干貨——ArrayList源碼分析

    摘要:關(guān)于的具體實(shí)現(xiàn),一些基本的都也知道,譬如數(shù)組實(shí)現(xiàn),線程不安全等等,但是更加具體的就很少去了解了,例如初始化的長(zhǎng)度,擴(kuò)容等。 前言 在之前的文章中我們提到過ArrayList,ArrayList可以說是每一個(gè)學(xué)java的人使用最多最熟練的集合了,但是知其然不知其所以然。關(guān)于ArrayList的具體實(shí)現(xiàn),一些基本的都也知道,譬如數(shù)組實(shí)現(xiàn),線程不安全等等,但是更加具體的就很少去了解了,例如:...

    wupengyu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<