ArrayList源码分析

来源:互联网 发布:lol老是网络断开连接 编辑:程序博客网 时间:2024/06/06 13:06

List:

  1. ArrayList:底层数组实现,线程不安全(不要觉得不安全就觉得不好),效率高。增删改查中查询快,其余比较慢

  2. LinkedList:底层链表实现,线程不安全,效率高。增删改查中查询慢,其余都快

  3. Vector:线程安全,但是效率低

ArrayList:

1.成员变量:

  • private static final long serialVersionUID = 8683452581122892189L
  • private transient Object[] elementData;
  • private int size;

说明:

serialVersionUID :和序列化有关,等了解完序列化后在补充。
elementData:实际存对象的数组
size:当前存放的对象的数量(不用说也是小于等于elementData的申请长度的)
transientjava语言的关键字,变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。换句话来说就是,用transient关键字标记的成员变量不参与序列化过程。

方法:

public

2.扩容函数(ensureCapacity)

 public void ensureCapacity(int minCapacity) {    modCount++;                 int oldCapacity = elementData.length;    if (minCapacity > oldCapacity) {        Object oldData[] = elementData;        int newCapacity = (oldCapacity * 3)/2 + 1;      //可以看到每次扩充1.5倍            if (newCapacity < minCapacity)        newCapacity = minCapacity;                  //扩容后如果还小那就直接扩到需要的大小。            // minCapacity is usually close to size, so this is a win:            elementData = Arrays.copyOf(elementData, newCapacity);    }    }

关于modCound

3.size

 public int size() {    return size;    }

4.isEmpty

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

5.contains(是否包含对象o)

public boolean contains(Object o) {    return indexOf(o) >= 0;         //indexOf(o)若对象o在该ArrayList中存在,返回下标,否则返回-1,下一个就是。    }

6.indexOf()

public int indexOf(Object o) {    if (o == null) {                //可以看到允许往ArrayList存入null        for (int i = 0; i < size; i++)        if (elementData[i]==null)            return i;    } else {        for (int i = 0; i < size; i++)        if (o.equals(elementData[i]))            return i;    }    return -1;    }

同时注意若在ArrayList中放入了多个相同的对象,那么只会返回最先找到的下标

7.lastIndexOf() //从后往前找

  public int lastIndexOf(Object o) {    if (o == null) {        for (int i = size-1; i >= 0; i--)        if (elementData[i]==null)            return i;    } else {        for (int i = size-1; i >= 0; i--)        if (o.equals(elementData[i]))            return i;    }    return -1;    }

8.clone :返回此 ArrayList 实例的浅表复制。(不复制这些元素本身。)
注意这是从Object重写过来的方法,所以用List多态时点不出来clone

 public Object clone() {    try {        ArrayList<E> v = (ArrayList<E>) super.clone();        v.elementData = Arrays.copyOf(elementData, size);        v.modCount = 0;        return v;    } catch (CloneNotSupportedException e) {        // this shouldn't happen, since we are Cloneable        throw new InternalError();    }    }

9.toArray() :就是将elementData给提取出来

  public Object[] toArray() {        return Arrays.copyOf(elementData, size);    }

10.toArray(T[] a)

public <T> T[] toArray(T[] a) {        if (a.length < size)        //如果给的数组放不下那就尽量放            // Make a new array of a's runtime type, but my contents:            return (T[]) Arrays.copyOf(elementData, size, a.getClass());            System.arraycopy(elementData, 0, a, 0, size);        if (a.length > size)        //如果指定的数组能容纳列表并有剩余空间(即数组的元素比列表的多),那么会将数组中紧跟在集合末尾的元素设置为 null。这对确定列表的长度很有用,但只 在调用方知道列表中不包含任何 null 元素时才有用。            a[size] = null;        return a;    }

11.get():返回指定下表的元素

public E get(int index) {    RangeCheck(index);    return (E) elementData[index];    }

12.set():修改给定下表的值

   public E set(int index, E element) {    RangeCheck(index);    E oldValue = (E) elementData[index];    elementData[index] = element;    return oldValue;    }

13.add(E e):给末尾添加e

 public boolean add(E e) {    ensureCapacity(size + 1);  // Increments modCount!!    elementData[size++] = e;    return true;    }

14.add(int index, E element):给指定位置添加

 public void add(int index, E element) {    if (index > size || index < 0)        throw new IndexOutOfBoundsException(        "Index: "+index+", Size: "+size);    ensureCapacity(size+1);  // Increments modCount!!    System.arraycopy(elementData, index, elementData, index + 1,             size - index);    elementData[index] = element;    size++;    }

arraycopy
public static void arraycopy(Object src,
int srcPos,
Object dest,
int destPos,
int length)

从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。从 src 引用的源数组到 dest 引用的目标数组,数组组件的一个子序列被复制下来。被复制的组件的编号等于 length 参数。源数组中位置在 srcPos 到 srcPos+length-1 之间的组件被分别复制到目标数组中的 destPos 到 destPos+length-1 位置。

  1. remove(int index)
 public E remove(int index) {    RangeCheck(index);    modCount++;    E oldValue = (E) elementData[index];    int numMoved = size - index - 1;    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                 numMoved);    elementData[--size] = null; // Let gc do its work    return oldValue;    }

16.remove(Object o)

 public boolean remove(Object o) {    if (o == null) {            for (int index = 0; index < size; index++)        if (elementData[index] == null) {            fastRemove(index);          //下面一个函数            return true;        }    } else {        for (int index = 0; index < size; index++)        if (o.equals(elementData[index])) {            fastRemove(index);            return true;        }        }    return false;    }

17.fastRemove(int index)

 private void fastRemove(int index) {        modCount++;        int numMoved = size - index - 1;        if (numMoved > 0)            System.arraycopy(elementData, index+1, elementData, index,                             numMoved);        elementData[--size] = null; // Let gc do its work    }

18.clear()

  public void clear() {    modCount++;    // Let gc do its work    for (int i = 0; i < size; i++)        elementData[i] = null;    size = 0;    }

19.addAll(Collection

public boolean addAll(Collection<? extends E> c) {    Object[] a = c.toArray();        int numNew = a.length;    ensureCapacity(size + numNew);  // Increments modCount        System.arraycopy(a, 0, elementData, size, numNew);        size += numNew;    return numNew != 0;    }

20.addAll(int index, Collection

 public boolean addAll(int index, Collection<? extends E> c) {    if (index > size || index < 0)        throw new IndexOutOfBoundsException(        "Index: " + index + ", Size: " + size);    Object[] a = c.toArray();    int numNew = a.length;    ensureCapacity(size + numNew);  // Increments modCount    int numMoved = size - index;    if (numMoved > 0)        System.arraycopy(elementData, index, elementData, index + numNew,                 numMoved);        System.arraycopy(a, 0, elementData, index, numNew);    size += numNew;    return numNew != 0;    }

protected方法

21.removeRange(int fromIndex, int toIndex):将这两个位置之间的元素都remove

protected void removeRange(int fromIndex, int toIndex) {    modCount++;    int numMoved = size - toIndex;        System.arraycopy(elementData, toIndex, elementData, fromIndex,                         numMoved);    // Let gc do its work    int newSize = size - (toIndex-fromIndex);    while (size != newSize)        elementData[--size] = null;    }

private方法

22.writeObject(java.io.ObjectOutputStream s)

  private void RangeCheck(int index) {    if (index >= size)        throw new IndexOutOfBoundsException(        "Index: "+index+", Size: "+size);    }    private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException{    // Write out element count, and any hidden stuff    int expectedModCount = modCount;    s.defaultWriteObject();        // Write out array length        s.writeInt(elementData.length);    // Write out all elements in the proper order.    for (int i=0; i<size; i++)            s.writeObject(elementData[i]);    if (modCount != expectedModCount) {            throw new ConcurrentModificationException();        }    }

23.readObject(java.io.ObjectInputStream s)

    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {    // Read in size, and any hidden stuff    s.defaultReadObject();        // Read in array length and allocate array        int arrayLength = s.readInt();        Object[] a = elementData = new Object[arrayLength];    // Read in all elements in the proper order.    for (int i=0; i<size; i++)            a[i] = s.readObject();    }}

2017-11-26更新:

容器类的所有父类/祖父类…..是AbstractCollection这个抽象类,这个类是直接继承了Object,而这个类中重写了Object的toString方法,用于遍历容器类.

代码:

 public String toString() {        Iterator<E> i = iterator();    if (! i.hasNext())        return "[]";    StringBuilder sb = new StringBuilder();    sb.append('[');    for (;;) {        E e = i.next();        sb.append(e == this ? "(this Collection)" : e);        if (! i.hasNext())        return sb.append(']').toString();        sb.append(", ");    }    }

所以(ArrayList对象).toString会以数组的形式显示该容器中包含的全部对象

原创粉丝点击