1. 程式人生 > >Java集合-ArrayList原始碼

Java集合-ArrayList原始碼

簡介

  • ArrayList是List介面的大小可變陣列的實現,ArrayList底層是用一個Object陣列來儲存元素,ArrayList允許儲存所有不同型別元素,包括null,允許插入重複元素(底層是一個Object陣列)
  • 在用迭代器遍歷ArrayList集合物件時,如果遍歷過程中對集合物件的內容進行了修改(增加、刪除、修改),則會丟擲ConcurrentModificationException,即迭代器的快速失敗(fail—fast)機制
  • ArrayList每次新增元素都會校驗底層陣列長度,陣列長度不夠時則擴容,擴容後,陣列擴大為原來的1.5倍
  • The size, isEmpty, get, set,iterator, and listIterator operations run in constant time. The add operation runs in amortized constant time,that is, adding n elements requires O(n) time. All of the other operations run in linear time (roughly speaking). The constant factor is low compared to that for the LinkedList implementation

類圖

這裡寫圖片描述

原始碼

繼承關係

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • RandomAccess 是一個標記介面(Marker interface),用於標明實現該介面的List支援快速隨機訪問,主要目的是使演算法能夠在隨機和順序訪問的list中表現的更加高效

  • Cloneable介面是一個空介面,僅用於標記物件,Cloneable接口裡面是沒有clone()方法,clone()方法是Object類裡面的方法

  • Serializable介面是啟用其序列化功能的介面。實現java.io.Serializable 介面的類是可序列化的。沒有實現此介面的類將不能使它們的任意狀態被序列化或逆序列化

建構函式

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
} else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } /** * Constructs an empty list with an initial capacity of ten. */ public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }

成員變數

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

/**
 * Shared empty array instance used for empty instances.
 */
private static final Object[] EMPTY_ELEMENTDATA = {};

/**
 * Shared empty array instance used for default sized empty instances. We
 * distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when
 * first element is added.
 */
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

/**
 * The array buffer into which the elements of the ArrayList are stored.
 * The capacity of the ArrayList is the length of this array buffer. Any
 * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
 * will be expanded to DEFAULT_CAPACITY when the first element is added.
 */
transient Object[] elementData; // non-private to simplify nested class access

/**
 * The size of the ArrayList (the number of elements it contains).
 *
 * @serial
 */
private int size;

成員方法

內部類ArrayListSpliterator

static final class ArrayListSpliterator<E> implements Spliterator<E> {
    private final ArrayList<E> list;
    private int index; // current index, modified on advance/split
    private int fence; // -1 until used; then one past last index
    private int expectedModCount; // initialized when fence set

    /** Create new spliterator covering the given  range */
    ArrayListSpliterator(ArrayList<E> list, int origin, int fence,
                         int expectedModCount) {
        this.list = list; // OK if null unless traversed
        this.index = origin;
        this.fence = fence;
        this.expectedModCount = expectedModCount;
    }

    private int getFence() { // initialize fence to size on first use
        int hi; // (a specialized variant appears in method forEach)
        ArrayList<E> lst;
        if ((hi = fence) < 0) {
            if ((lst = list) == null)
                hi = fence = 0;
            else {
                expectedModCount = lst.modCount;
                hi = fence = lst.size;
            }
        }
        return hi;
    }

    public ArrayListSpliterator<E> trySplit() {
        int hi = getFence(), lo = index, mid = (lo + hi) >>> 1;
        return (lo >= mid) ? null : // divide range in half unless too small
            new ArrayListSpliterator<E>(list, lo, index = mid,
                                        expectedModCount);
    }

    public boolean tryAdvance(Consumer<? super E> action) {
        if (action == null)
            throw new NullPointerException();
        int hi = getFence(), i = index;
        if (i < hi) {
            index = i + 1;
            @SuppressWarnings("unchecked") E e = (E)list.elementData[i];
            action.accept(e);
            if (list.modCount != expectedModCount)
                throw new ConcurrentModificationException();
            return true;
        }
        return false;
    }

    public void forEachRemaining(Consumer<? super E> action) {
        int i, hi, mc; // hoist accesses and checks from loop
        ArrayList<E> lst; Object[] a;
        if (action == null)
            throw new NullPointerException();
        if ((lst = list) != null && (a = lst.elementData) != null) {
            if ((hi = fence) < 0) {
                mc = lst.modCount;
                hi = lst.size;
            }
            else
                mc = expectedModCount;
            if ((i = index) >= 0 && (index = hi) <= a.length) {
                for (; i < hi; ++i) {
                    @SuppressWarnings("unchecked") E e = (E) a[i];
                    action.accept(e);
                }
                if (lst.modCount == mc)
                    return;
            }
        }
        throw new ConcurrentModificationException();
    }

    public long estimateSize() {
        return (long) (getFence() - index);
    }

    public int characteristics() {
        return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;
    }
}

內部類Itr

private class Itr implements Iterator<E> {
  int cursor;       // index of next element to return
  int lastRet = -1; // index of last element returned; -1 if no such
  int expectedModCount = modCount;

  public boolean hasNext() {
      return cursor != size;
  }

  @SuppressWarnings("unchecked")
  public E next() {
      checkForComodification();
      int i = cursor;
      if (i >= size)
          throw new NoSuchElementException();
      Object[] elementData = ArrayList.this.elementData;
      if (i >= elementData.length)
          throw new ConcurrentModificationException();
      cursor = i + 1;
      return (E) elementData[lastRet = i];
  }

  public void remove() {
      if (lastRet < 0)
          throw new IllegalStateException();
      checkForComodification();

      try {
          ArrayList.this.remove(lastRet);
          cursor = lastRet;
          lastRet = -1;
          expectedModCount = modCount;
      } catch (IndexOutOfBoundsException ex) {
          throw new ConcurrentModificationException();
      }
  }

  @Override
  @SuppressWarnings("unchecked")
  public void forEachRemaining(Consumer<? super E> consumer) {
      Objects.requireNonNull(consumer);
      final int size = ArrayList.this.size;
      int i = cursor;
      if (i >= size) {
          return;
      }
      final Object[] elementData = ArrayList.this.elementData;
      if (i >= elementData.length) {
          throw new ConcurrentModificationException();
      }
      while (i != size && modCount == expectedModCount) {
          consumer.accept((E) elementData[i++]);
      }
      // update once at end of iteration to reduce heap write traffic
      cursor = i;
      lastRet = i - 1;
      checkForComodification();
  }

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

內部類ListItr

private class ListItr extends Itr implements ListIterator<E> {
    ListItr(int index) {
        super();
        cursor = index;
    }

    public boolean hasPrevious() {
        return cursor != 0;
    }

    public int nextIndex() {
        return cursor;
    }

    public int previousIndex() {
        return cursor - 1;
    }

    @SuppressWarnings("unchecked")
    public E previous() {
        checkForComodification();
        int i = cursor - 1;
        if (i < 0)
            throw new NoSuchElementException();
        Object[] elementData = ArrayList.this.elementData;
        if (i >= elementData.length)
            throw new ConcurrentModificationException();
        cursor = i;
        return (E) elementData[lastRet = i];
    }

    public void set(E e) {
        if (lastRet < 0)
            throw new IllegalStateException();
        checkForComodification();

        try {
            ArrayList.this.set(lastRet, e);
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }

    public void add(E e) {
        checkForComodification();

        try {
            int i = cursor;
            ArrayList.this.add(i, e);
            cursor = i + 1;
            lastRet = -1;
            expectedModCount = modCount;
        } catch (IndexOutOfBoundsException ex) {
            throw new ConcurrentModificationException();
        }
    }
}

內部類SubList

private class SubList extends AbstractList<E> implements RandomAccess {
    private final AbstractList<E> parent;
    private final int parentOffset;
    private final int offset;
    int size;

    SubList(AbstractList<E> parent,
            int offset, int fromIndex, int toIndex) {
        this.parent = parent;
        this.parentOffset = fromIndex;
        this.offset = offset + fromIndex;
        this.size = toIndex - fromIndex;
        this.modCount = ArrayList.this.modCount;
    }

    public E set(int index, E e) {
        rangeCheck(index);
        checkForComodification();
        E oldValue = ArrayList.this.elementData(offset + index);
        ArrayList.this.elementData[offset + index] = e;
        return oldValue;
    }

    public E get(int index) {
        rangeCheck(index);
        checkForComodification();
        return ArrayList.this.elementData(offset + index);
    }

    public int size() {
        checkForComodification();
        return this.size;
    }

    public void add(int index, E e) {
        rangeCheckForAdd(index);
        checkForComodification();
        parent.add(parentOffset + index, e);
        this.modCount = parent.modCount;
        this.size++;
    }

    public E remove(int index) {
        rangeCheck(index);
        checkForComodification();
        E result = parent.remove(parentOffset + index);
        this.modCount = parent.modCount;
        this.size--;
        return result;
    }

    protected void removeRange(int fromIndex, int toIndex) {
        checkForComodification();
        parent.removeRange(parentOffset + fromIndex,
                           parentOffset + toIndex);
        this.modCount = parent.modCount;
        this.size -= toIndex - fromIndex;
    }

    public boolean addAll(Collection<? extends E> c) {
        return addAll(this.size, c);
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        int cSize = c.size();
        if (cSize==0)
            return false;

        checkForComodification();
        parent.addAll(parentOffset + index, c);
        this.modCount = parent.modCount;
        this.size += cSize;
        return true;
    }

    public Iterator<E> iterator() {
        return listIterator();
    }

    public ListIterator<E> listIterator(final int index) {
        checkForComodification();
        rangeCheckForAdd(index);
        final int offset = this.offset;

        return new ListIterator<E>() {
            int cursor = index;
            int lastRet 
            
           

相關推薦

Java集合-ArrayList原始碼

簡介 ArrayList是List介面的大小可變陣列的實現,ArrayList底層是用一個Object陣列來儲存元素,ArrayList允許儲存所有不同型別元素,包括null,允許插入重複元素(底層是一個Object陣列) 在用迭代器遍歷ArrayL

java集合核心原始碼01——ArrayList

首先呢,對於ArrayList,相當於一個動態陣列,裡面可以儲存重複資料,並且支援隨機訪問,不是執行緒安全的。對於更多的底層東西,且聽分解。 開啟原始碼,先看繼承了哪些類,實現了哪些介面,然後繼承的這些類或介面是否還有父類,一直深挖到頂部   public class ArrayList

Java集合原始碼解析:ArrayList

目錄 前言 今天學習一個Java集合類使用最多的類 ArrayList , ArrayList 繼承了 AbstractList,並實現了List 和 RandomAccess 等介面, public class ArrayList<E> extends AbstractList<E>

java集合原始碼詳解-ArrayList(2)

上次關於ArrayList的結構沒有做總結。這次還是補充在自己部落格裡面吧。 ArrayList繼承自一個抽象類。實現了四個介面。 AbstractList繼承自AbstractCollection。AbstractCollection繼承自Object。 ArrayL

java集合原始碼詳解-ArrayList(5)

上次,測試了java集合類支援遍歷方式的效率比較,今天再通過斷電除錯,去ArrayList底層的迭代器做了什麼。 首先在迭代器這裡打上斷電,(在實際中變數ArrayList最後別用迭代器,因為他很慢) 可以看到這個iterator()方法返回值是一個迭代器,函式體是r

java集合原始碼詳解-ArrayList(1)

       最近在瘋狂的補基礎 在java中 最重要的知識之一 非集合類莫屬。這次在學習java集合類原始碼,採用的是傳統的方法,斷點除錯和寫測試程式碼。由於是剛開始接觸java集合類原始碼。所以一開始只寫了兩句程式碼來測試,畢竟原始碼學習是很緩慢的過程。只能慢慢的啃。在閱

java-集合arraylist

坑點 做題常用: 陣列轉變 Arraylist.asList() 實際上傳的是一個可變長引數,呼叫了內部類,基礎型別的陣列由於 不是封裝類(猜測java對封裝型別的陣列和變長引數有過轉換處理,形如scala隱式抓換),導致基本型別陣列,在<>

Java集合——LinkedList原始碼分析

一 前言 上一篇我們介紹了ArrayList原始碼解析有想看的同學可以點選這個連結ArrayList原始碼解析。平時我們或多或少都用過LinKedList,但是對其原理不是很瞭解,我們就來一起學習吧。 二 原始碼解析 1. LinkedList概述 LinkedList是

Java集合原始碼解析:AbstractMap

目錄 引言 原始碼解析 抽象函式entrySet() 兩個集合檢視 操作方法 兩個子類 參考: 引言 今天學習一個Java集合的一個抽象類 AbstractMap ,AbstractMap 是Map介面的 實現類之一,也是HashMap、T

Java集合原始碼解析:HashMap (基於JDK1.8)

目錄 前言 HashMap的資料結構 深入原始碼 兩個引數 成員變數 四個構造方法 插入資料的方法:put() 雜湊函式:hash() 動態擴容:resize() 節點樹化、紅黑樹的拆分 節點樹化

Java集合原始碼解析:Vector

引言 之前的文章我們學習了一個集合類 ArrayList,今天講它的一個兄弟 Vector。 為什麼說是它兄弟呢?因為從容器的構造來說,Vector 簡直就是 ArrayList 的翻版,也是基於陣列的資料結構,不同的是,Vector的每個方法都加了 synchronized 修飾符,是執行緒安全的。 類

Java基礎—ArrayList原始碼淺析

注:以下原始碼均為JDK8的原始碼 一、 核心屬性   基本屬性如下:      核心的屬性其實是紅框中的兩個:      //從註釋也容易看出,一個是集合元素,一個是集合長度(注意是邏輯長度,即元素的個數,而非陣列長度)   其中:transient指明序列化時請忽略。  二、構造

Java集合--LinkedHashMap原始碼分析

概述 分析一下 LinkedHashMap 原始碼,看下內部結構,研究一下如何保證訪問順序。 繼承關係 public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V

Java集合--ArrayList

概述 ArrayList 是一個數組集合,容量能夠動態增長,並且提供了隨機訪問的功能,在平時工作中用的很頻繁,通過原始碼研究一下內部的實現機制。 繼承關係 public class ArrayList<E> extends AbstractList<E>

java集合ArrayList

陣列可以儲存多個元素,但在某些情況下無法確定到底要儲存多少個元素,此時陣列將不再適用,因為陣列的長度不可變。 為了儲存這些數目不確定的元素,JDK中提供了一系列特殊的類,這些類可以儲存任意型別的元素,並且長度可變,統稱為集合。 ArrayList集合是程式中最常見的一種集合,它屬於引用資料型別(類)。在A

Java集合---ArrayList(2)

用途與特點 可用於在需要儲存有序的,可動態擴充集合大小的情況使用。可以看做是一個動態的陣列。雖然該集合理論上是可以動態無限擴充,但也有最大長度現實, 實現演算法 ArrayList的底層實現方式其實就是Object[]陣列實現,更具封裝會儲存實際儲存大小Size物件,與存放資料的elementData。 預設

Java集合 | LinkedList 原始碼分析(JDK 1.8)

一、基本圖示 二、基本介紹 public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, De

java集合原始碼詳解-LinkedList(4)-基於JDK8

LinkedList 裡面還有個具有新增功能的函式,上回學漏了,這回補上。 它就是linkBefore()------在一個非空節點前,插入資料 這裡打上個斷點 點選下一步。先把size除二  ,去比較。具體的這個node()方法,我們之前學過,這裡跳過。這個方法,其實就

Java集合&Spring原始碼淺讀

記錄自己現在知道的,以後瞭解了更多的話,再繼續補上來 Java集合類 Collection 介面 說明:是List,set 的父類。定義了集合初始模樣。集合只儲存物件。 Jdk8文件,內部方法定義有: List介面 說明:有序集合,可重複,繼承Collection。常用實現類ArrayList,L

JAVA集合-03ArrayList原始碼解析和使用例項

上一章講解了Collection介面下得抽象類和繼承介面,後續深入到具體的實現類,部落格及對應得程式碼可在github上檢視 ArrayList簡介 ArrayList底層實現是陣列,相較於陣列固定大小,ArrayList可以動態的增加;ArrayList繼承AbstractCollect