亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

Java源碼分析之ArrayList

2019-11-15 01:14:14
字體:
來源:轉載
供稿:網友
java源碼分析之ArrayList

ArrayList是以數組為基準的容器類,和LinkedList(鏈表)正好相反。因而ArrayList擁有更好的查找性能,增刪操作則差一些。ArrayList封裝了對于常規數組的操作,同時可以自動擴展容量。

下面對ArrayList的API進行歸類:

1、構造函數:

①ArrayList()  以空數組進行構造  

②ArrayList(int) 以指定大小的容量初始化數組

③ArrayList(Collection)  以指定集合構造ArrayList的數組元素

2、增加元素:

①boolean add(E)  在數組末尾加入指定元素

②void add(int,E)  在第一個參數指定的索引處插入元素,后面所有元素后移一個位置

③boolean addAll(Collection)  在數組末尾加入集合的所有元素

④boolean addAll(int,Collection) 在指定索引處加入集合所有元素

3、刪除元素:

①E remove(int)  移除索引處元素,之后的所有元素前移一位

②boolean remove(Object)  查找到指定元素,刪除之,未刪除成功false

③void removeRange(int,int) 刪除指定區間的所有元素,刪除第一個索引處,但不刪除最后一個索引處

④void clear()  刪除所有元素

4、更改元素:

 set(int,Object)  將指定索引處的值修改為指定的值

5、查找:

①E get(int)  返回指定索引處的元素

②boolean contains(Object)  確定是否包含該元素

③int indexOf(Object)  從前往后查找指定元素的索引,找不到返回-1

④int lastIndexOf(Object)  從后往前查找元素索引,找不到返回-1

⑤int size()  返回包含的元素個數

⑥boolean isEmpty()  確定數組是否為空

6、其他操作:

①Object[] toArray()  返回Object數組,每個Object對應ArrayList的一個元素

②T[] toArray(T[])  返回T類型數組,每個T對應ArrayList的一個實際類型的元素

③void trimToSize()  刪除數組最后冗余的值為null的元素

④void ensureCapacity(int)  使數組容量擴充為指定的容量

⑤Object clone()    復制一個除了內存地址其他信息完全一樣的ArrayList

接下來進行源碼解析

一、ArrayList包含的成員變量和常量:

transient Object[] array;    //ArrayList的核心,所有操作都圍繞它展開,ArrayList類似于數組的包裝類int size;    //數組包含的實際元素個數,不是數組容量,為了滿足添加元素時數組不必多次擴容,必須預先將容量設定為某個略大些的值。這樣就不能用array.length得到元素個數了

二、構造函數3種

    //不給參數,用空數組初始    public ArrayList() {        array = EmptyArray.OBJECT;    }
  //用一個已有的容器對象初始化數組  public ArrayList(Collection<? extends E> collection) {        if (collection == null) {            throw new NullPointerException("collection == null");        }        Object[] a = collection.toArray();        if (a.getClass() != Object[].class) {//這個過程看不懂            Object[] newArray = new Object[a.length];            System.arraycopy(a, 0, newArray, 0, a.length);    //數組復制操作            a = newArray;        }        array = a;        size = a.length;    }
   //用指定初始容量初始化數組,當容量可以確定的時候用這個方法可以避免多次更改數組大小,提高性能    public ArrayList(int capacity) {        if (capacity < 0) {            throw new IllegalArgumentException("capacity < 0: " + capacity);        }        array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);    }

三、增加元素

  這應該是ArrayList中最復雜的操作了,因為涉及到容量擴充的操作,也是ArrayList和數組最大的區別——自動擴容。但是因為涉及到重新分配內存空間和數組整個復制,多次擴容會影響性能

 

    @Override     public boolean add(E object) {        Object[] a = array;        //用一個代表,減少書寫量        int s = size;        if (s == a.length) {    //數組已滿,必須先擴容        //注意這邊的擴容策略,必須先開辟一片更大的內存空間,再執行數組復制操作       //具體新數組取多大,如果當前容量小于最小容量增長值的一半,則按這個值增長;否則即原來容量足夠大,在原來容量基礎上增加一半            Object[] newArray = new Object[s +                    (s < (MIN_CAPACITY_INCREMENT / 2) ?                     MIN_CAPACITY_INCREMENT : s >> 1)];            System.arraycopy(a, 0, newArray, 0, s);  //數組復制操作            array = a = newArray;        }        a[s] = object;    //現在容量足夠了,在新數組末尾直接加上這個新元素        size = s + 1;    //別忘了現在元素個數加了一個,必須保持同步        modCount++;  //修改次數加1        return true;    }

    //對上面的擴容操作進行了抽象,可能因為上面的操作更頻繁,所以直接把擴容操作寫在代碼里面以提高性能吧    PRivate static int newCapacity(int currentCapacity) {        int increment = (currentCapacity < (MIN_CAPACITY_INCREMENT / 2) ?                MIN_CAPACITY_INCREMENT : currentCapacity >> 1);        return currentCapacity + increment;    }        //在指定位置插入,除了數組復制操作的范圍不同,其他都一樣    @Override     public void add(int index, E object) {        Object[] a = array;        int s = size;        if (index > s || index < 0) {            throwIndexOutOfBoundsException(index, s);        }        if (s < a.length) {            System.arraycopy(a, index, a, index + 1, s - index);        } else {            // assert s == a.length;            Object[] newArray = new Object[newCapacity(s)];            System.arraycopy(a, 0, newArray, 0, index);            System.arraycopy(a, index, newArray, index + 1, s - index);            array = a = newArray;        }        a[index] = object;        size = s + 1;        modCount++;    }

四、刪除元素

    //這里數組相比鏈表的劣勢就很明顯了,刪除指定位置的值很簡單,但是為了保持后面操作的穩定性,必須將之后的所有值前移一個位置,需要O(n)的時間,而鏈表只要O(1)。    //這里得到一個很重要的啟示:如果要移除多個連續的元素,用for循環配合這個方法會非常損耗性能,應該用下面的removeRange方法    @Override     public E remove(int index) {        Object[] a = array;        int s = size;        if (index >= s) {            throwIndexOutOfBoundsException(index, s);        }        @SuppressWarnings("unchecked")        E result = (E) a[index];   //因為每個元素都是Object類型,必須強轉        System.arraycopy(a, index + 1, a, index, --s - index);        a[s] = null;  // 防止內存占用過多,不用的值置為null,給系統及時回收        size = s;        modCount++;        return result;    }   //移除連續區間的元素,只需執行一次arrayCopy操作   @Override protected void removeRange(int fromIndex, int toIndex) {        if (fromIndex == toIndex) {            return;        }        Object[] a = array;        int s = size;        if (fromIndex >= s) {            throw new IndexOutOfBoundsException("fromIndex " + fromIndex                    + " >= size " + size);        }        if (toIndex > s) {            throw new IndexOutOfBoundsException("toIndex " + toIndex                    + " > size " + size);        }        if (fromIndex > toIndex) {            throw new IndexOutOfBoundsException("fromIndex " + fromIndex                    + " > toIndex " + toIndex);        }        System.arraycopy(a, toIndex, a, fromIndex, s - toIndex);        int rangeSize = toIndex - fromIndex;        Arrays.fill(a, s - rangeSize, s, null);   //不用的索引處全部置null        size = s - rangeSize;        modCount++;    }    //需要依次對每一個元素進行比較,性能也不好    //可以看出這個方法只會刪除第一個出現的元素,如果存在equals比較后相同的元素,還有遺留    @Override     public boolean remove(Object object) {        Object[] a = array;        int s = size;        if (object != null) {            for (int i = 0; i < s; i++) {                if (object.equals(a[i])) {                    System.arraycopy(a, i + 1, a, i, --s - i);                    a[s] = null;  // Prevent memory leak                    size = s;                    modCount++;                    return true;                }            }        } else {            for (int i = 0; i < s; i++) {                if (a[i] == null) {                    System.arraycopy(a, i + 1, a, i, --s - i);                    a[s] = null;  // Prevent memory leak                    size = s;                    modCount++;                    return true;                }            }        }        return false;    }  

    //這里可以看出是通過將每個元素依次置為null,也需要O(n)時間;并不改變數組容量    @Override     public void clear() {        if (size != 0) {            Arrays.fill(array, 0, size, null);            size = 0;            modCount++;        }    }

五、修改元素值

    //修改元素值很簡單,跟數組操作一樣,只要O(1)時間就能完成,同時返回被修改的舊值    @Override     public E set(int index, E object) {        Object[] a = array;        if (index >= size) {            throwIndexOutOfBoundsException(index, size);        }        @SuppressWarnings("unchecked")         E result = (E) a[index];        a[index] = object;        return result;    }    

六、查找操作

    //查找操作是ArrayList最大的優勢,因為數組在內存中占用連續的存儲區域,只要O(1)時間就能找到指定索引所對應的值    @SuppressWarnings("unchecked")     @Override     public E get(int index) {        if (index >= size) {            throwIndexOutOfBoundsException(index, size);        }        return (E) array[index];    }

七、其他操作

  關于ArrayList向數組轉換(其實是返回ArrayList的成員數組的拷貝)

    /*這兩個方法經常會搞混,包括我初學的時候也不知道是怎么回事。第一種方法貌似很簡單,但是因為返回的是Object數組,后續如果要對這個返回的數組操作一般要轉換為具體的類型,就還要對該數組的每個元素都強轉一次。而第二個方法傳入一個給定的數組,這個數組是指定了具體的類型的,因而返回后這個數組可以直接用。通常傳入一個空數組 new T[]{}即可。    */    @Override     public Object[] toArray() {        int s = size;        Object[] result = new Object[s];        System.arraycopy(array, 0, result, 0, s);        return result;    }    /*這里有一點讓我不明白,為什么泛型要選擇T而不是E?如果T和E不一致,arraycopy操作會成功嗎?*/    @Override     public <T> T[] toArray(T[] contents) {        int s = size;        if (contents.length < s) {  //如果提供的數組不夠放,重新開辟內存            @SuppressWarnings("unchecked")             T[] newArray                = (T[]) Array.newInstance(contents.getClass().getComponentType(), s);            contents = newArray;        }        System.arraycopy(this.array, 0, contents, 0, s);        if (contents.length > s) {            contents[s] = null;    //這里也讓我不明白,為什么只把s處置為null,s以后的不也應該置為null嗎?        }        return contents;    }    


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品中文字| 久久99久久久久久久噜噜| 欧美洲成人男女午夜视频| 中文字幕日韩欧美在线视频| 亚洲国产精品成人va在线观看| 亚洲欧洲美洲在线综合| 国产精品久久久久7777婷婷| 亚洲老头老太hd| 中文字幕精品一区二区精品| 欧美性开放视频| 久久亚洲综合国产精品99麻豆精品福利| 亚洲成人999| 国产午夜精品理论片a级探花| 日韩在线播放av| 欧美日韩国产一区中文午夜| 精品国产一区二区三区在线观看| 日韩经典中文字幕在线观看| 久久中文字幕在线视频| 国产视频在线观看一区二区| 国产欧美久久一区二区| 精品久久久久久久久中文字幕| 亚洲自拍偷拍视频| 亚洲国产精品久久精品怡红院| 欧美理论电影在线观看| 欧美视频不卡中文| 色综合天天综合网国产成人网| 亚洲女性裸体视频| 97精品国产97久久久久久免费| 91产国在线观看动作片喷水| 久久理论片午夜琪琪电影网| 久久不射热爱视频精品| 成人激情视频网| 久久久最新网址| 日韩欧美成人区| 国内精品小视频| 欧美在线亚洲在线| 久久男人av资源网站| 97精品在线观看| 国产精品电影网| 日韩av色在线| 亚洲国模精品一区| 亚洲va久久久噜噜噜久久天堂| 亚洲成人激情视频| 激情久久av一区av二区av三区| 久久6免费高清热精品| 2019中文在线观看| 亚洲夜晚福利在线观看| 97精品视频在线播放| 亚洲精品成人久久电影| 国产成人jvid在线播放| 欧美大尺度在线观看| 国产成人91久久精品| 欧美日韩免费区域视频在线观看| 91在线精品视频| 欧美日韩国产黄| 91精品久久久久| 久久69精品久久久久久久电影好| 日韩成人中文字幕在线观看| 大量国产精品视频| 国产精品成人品| 日韩**中文字幕毛片| 久久久久久12| 亚洲欧美色婷婷| 亚洲精品国产精品久久清纯直播| 日韩电影免费观看中文字幕| 欧美丝袜一区二区三区| 91av视频在线观看| 亚洲国产成人久久| 欧美刺激性大交免费视频| 国产精品www网站| 欧美一区二区三区精品电影| 亚洲国产精品嫩草影院久久| 8x拔播拔播x8国产精品| 久久精品国产99国产精品澳门| 911国产网站尤物在线观看| 91在线网站视频| 亚洲视频精品在线| www.久久撸.com| 亚洲激情 国产| 成人免费黄色网| 精品国产美女在线| 夜夜狂射影院欧美极品| 亚洲精品久久久久久久久久久| 欧美成人免费一级人片100| 欧美极品美女视频网站在线观看免费| 综合久久五月天| 亚洲国产精品推荐| 2019中文字幕在线观看| 日韩精品在线免费观看| 日本高清不卡在线| 久久久噜噜噜久久久| 国产精品美女免费看| 亚洲精品美女免费| 国模gogo一区二区大胆私拍| 欧美肥臀大乳一区二区免费视频| 色无极亚洲影院| 人人澡人人澡人人看欧美| 亚洲精品美女在线观看| 久精品免费视频| 中文字幕久精品免费视频| 欧美贵妇videos办公室| 中文欧美日本在线资源| 亚洲一区中文字幕在线观看| 国产精品夜色7777狼人| 国产国语刺激对白av不卡| 欧美高清一级大片| 日韩在线不卡视频| 日韩av手机在线看| 日韩视频精品在线| 中文字幕9999| 91精品美女在线| 国产精品电影在线观看| 最新69国产成人精品视频免费| 永久555www成人免费| 日韩欧美亚洲成人| 色噜噜狠狠狠综合曰曰曰88av| 国产一级揄自揄精品视频| 久久夜色精品国产亚洲aⅴ| 91av在线精品| 精品中文字幕在线| 国产精品久久久久aaaa九色| 中文字幕在线看视频国产欧美| 国产精品久久久精品| 亚洲美女动态图120秒| 亚洲欧美日韩爽爽影院| 日韩av免费观影| 久久久免费高清电视剧观看| 色妞在线综合亚洲欧美| 精品中文字幕在线观看| 中国china体内裑精亚洲片| 国产一区二区免费| 久久久99免费视频| 国产区精品视频| 欧美激情第6页| 欧美人在线视频| 中文字幕av一区二区三区谷原希美| 欧美日韩精品国产| 2019av中文字幕| 亚洲精品成人网| 欧美大学生性色视频| 韩国19禁主播vip福利视频| 免费不卡欧美自拍视频| 中文字幕国产精品| 国产69精品99久久久久久宅男| 日韩精品视频中文在线观看| 欧美在线视频在线播放完整版免费观看| 这里只有精品久久| 欧美一区二区三区免费观看| 成人天堂噜噜噜| 永久555www成人免费| 青青草国产精品一区二区| 国产精品444| 成人黄色在线免费| 亚洲男人的天堂网站| 亚洲在线一区二区| 一区二区三区四区在线观看视频| 国产精品91一区| 日韩黄在线观看| 欧美一级片在线播放| 91理论片午午论夜理片久久| 久久久久久中文字幕| 日韩av在线电影网| 久久伊人色综合| 久久久久九九九九|