【Java Collection】常见 List 子类剖析(三)

我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码


一、架构

1.1 常见子类 UML

在这里插入图片描述

1.2 简述


二、 RandomAccess 接口子类

2.1 ArrayList 类

2.2 Vector 类

2.3 CopyOnWriteArrayList 类

2.4 ImmutableList 类

=== 点击查看top目录 ===


三、 AbstractSequentialList 抽象类子类

3.1 LinkedList 类


四、ArrayList 类

在这里插入图片描述

  • java.util.ArrayList
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • 注意:实现了 RandomAccess,表明是支持随机访问,那么也就是内部是数组Array 结构。

4.1 变量

变量名 备注
private static final int DEFAULT_CAPACITY = 10 内部Array数组默认长度,不够再扩容。
private static final Object[] EMPTY_ELEMENTDATA = {} 空数组。(标志性的)构造方法、trimToSize 、readObject用到
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 确定容量用的。我们将此与EMPTY_ELEMENTDATA区分开来,以了解在添加第一个元素时要膨胀多少。ensureCapacity、calculateCapacity 用到
transient Object[] elementData 元素数组
private int size 数组长度

=== 点击查看top目录 ===

4.2 方法

4.2.1 初始化(3个)
  • 默认构造方法
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  • 带initialCapacity构造方法
    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);
        }
    }
  • 带 Collection 的构造方法
    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;
        }
    }
  • 三构造方法,注意一下 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 与 EMPTY_ELEMENTDATA 的区别,前面那个是默认的。

=== 点击查看top目录 ===

3.2.2 get 与 set 方法
    public E get(int index) {
        rangeCheck(index);
        return elementData(index);
    }
   public E set(int index, E element) {
        rangeCheck(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }

都是先检查下标是否溢出,然后再进行 get 或者 set。

=== 点击查看top目录 ===

4.2.3 add 方法
  • java.util.ArrayList#add(E)
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
  1. 先检查数组内部容量 ensureCapacityInternal
  2. 设置元素

=== 点击查看top目录 ===

4.2.4 ensureCapacityInternal 方法
  • java.util.ArrayList#ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
  1. calculateCapacity 先计算所需要数组容量
  2. ensureExplicitCapacity 确保容量充足,必要时候扩容
4.2.5 calculateCapacity 方法
  • java.util.ArrayList#calculateCapacity (计算所需要数组容量 )
private static int calculateCapacity(Object[] elementData, int minCapacity) {
		// 若是默认的,也即是调用了
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
  1. ArrayList默认构造方法下,会进行扩容到合适的容量。
  2. 返回最少需要的容量
  • 上层调用:
    -
  1. ensureCapacityInternal 确保合适容量
  2. readObject 从输入流转换成 List 会用到

=== 点击查看top目录 ===

4.2.6 ensureExplicitCapacity 方法
  • java.util.ArrayList#ensureExplicitCapacity
private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
  1. modCount++ ,那么加入你在Iterator遍历,那么你就会抛出 ConcurrentModificationException
  2. 判断是否能够装下新元素,不够的话就 grow

=== 点击查看top目录 ===

4.2.7 grow 方法
  • java.util.ArrayList#grow
  • 容量增长方法,内部是调用 native 方法进行复制。
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        // 
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
  • 此处应该注意,如果每次添加一个元素都要进行扩容的话,那么及其浪费性能。

=== 点击查看top目录 ===

4.2.8 remove 方法
方法名 备注
public E remove(int index) 按 index 删除
public boolean remove(Object o) 按 Object 删除
public boolean removeIf(Predicate<? super E> filter) 按条件删除
protected void removeRange(int fromIndex, int toIndex) 删除一定范围内的元素
public boolean removeAll(Collection<?> c) 批量删除
  • java.util.ArrayList#remove(int) 删除 index 下标的元素
public E remove(int index) {
        rangeCheck(index);

        modCount++;
        E oldValue = elementData(index);

        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work

        return oldValue;
    }

内部原理:

  1. 拿到老的 Element ,待会返回
  2. 使用 native 底层的复制方法,把 index+1 以及后面的元素全部复制到index的位置来。
  3. 最后一个元素设置为null
  4. size - 1

=== 点击查看top目录 ===

  • java.util.ArrayList#remove(java.lang.Object) 删除某个元素
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;
    }

内部原理:

  1. 拿到老的 Element
  2. 使用 native 底层的复制方法,把 index+1 以及后面的元素全部复制到index的位置来。fastRemove方法
  3. 最后一个元素设置为null
  4. size - 1
  5. return true / false
  • 注意一下:若有100w个数据,你从头删到尾巴,那么肯定非常耗时。因为每次都要进行复制。

=== 点击查看top目录 ===

4.2.9 removeAll 方法
  • java.util.ArrayList#removeAll
  • 把Collection中包含c集合中的元素都移除掉(求差集)
public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }

=== 点击查看top目录 ===

4.2.10 batchRemove 方法(private)
  • java.util.ArrayList#batchRemove
private boolean batchRemove(Collection<?> c, boolean complement) {
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            // r != size 的情况: c.contains() 丢出 Exception,(看下 java.util.AbstractCollection#contains )
            if (r != size) {
                // 如果丢出异常,那么把后面没处理的都给衔接上放在原 elementData 上面
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            // retainAll 情况下:如果 w == size ,那么说明原来的Collection 与要处理的 Collection 一模一样
            // removeAll 情况下:如果 w == size ,那么一个没删除
            // 那么 w!= size 是什么情况呢?就是上面for处理后,w 后面还有元素,后面的元素都不要了,需要设置为 null,协助 gc
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }
  • 看下上层引用
    在这里插入图片描述
  • retainAll 与 removeAll
for (; r < size; r++)
       if (c.contains(elementData[r]) == complement)
            elementData[w++] = elementData[r];

---
retainAll:

elementData : A B C D F G
c : A C E

size = 10 
elementData : A C 
---

removeAll:

elementData : A B C D F G
c : A C E

size = 10 
elementData : B D F G

=== 点击查看top目录 ===

4.2.11 retainAll 方法
  • java.util.ArrayList#retainAll 方法
  • 把Collection中不是c的元素移除掉(求合集)
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    }

=== 点击查看top目录 ===

4.2.12 trimToSize 方法
  • java.util.ArrayList#trimToSize 方法
  • 压缩容量,假如内存1w的数组里面只有1000个元素,调用这个方法就是把这1000个元素copy到另外一个新的数组,指针指向这个新的数组。
public void trimToSize() {
        modCount++;
        if (size < elementData.length) {
            elementData = (size == 0)
              ? EMPTY_ELEMENTDATA
              : Arrays.copyOf(elementData, size);
        }
    }

=== 点击查看top目录 ===

4.2.13 fastRemove 方法 (private)
  • java.util.ArrayList#fastRemove 方法
    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; // clear to let GC do its work
    }
4.2.14 clear 方法
  • java.util.ArrayList#clear 方法
    public void clear() {
        modCount++;
        // clear to let GC do its work
        for (int i = 0; i < size; i++)
            elementData[i] = null;

        size = 0;
    }
  1. 数组内元素指针全部指向null,协助GC
  2. size 设置为 0
  • 思考下,为什么不直接 elementData = null

我自己的看法:如果你不想用这个list了,那么直接 list = null,如果你还想用,那么就调用 clear,免得你待会还得再 new 一个。

=== 点击查看top目录 ===

4.2.15 subList 方法
  • java.util.ArrayList#subList 方法
  • 浅复制,得到子List,实际上操作的还是父本身的list内部元素,详情看内部类 subList 实现
public List<E> subList(int fromIndex, int toIndex) {
        subListRangeCheck(fromIndex, toIndex, size);
        return new SubList(this, 0, fromIndex, toIndex);
    }

static void subListRangeCheck(int fromIndex, int toIndex, int size) {
    if (fromIndex < 0)
        throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
    if (toIndex > size)
        throw new IndexOutOfBoundsException("toIndex = " + toIndex);
    if (fromIndex > toIndex)
        throw new IllegalArgumentException("fromIndex(" + fromIndex +
                                           ") > toIndex(" + toIndex + ")");
}

=== 点击查看top目录 ===

4.2.16 writeObject 方法
  • java.util.ArrayList#writeObject 方法
  • 将 Collection 写入输出流 ObjectOutputStream
    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 size as capacity for behavioural compatibility with clone()
        s.writeInt(size);

        // 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();
        }
    }

=== 点击查看top目录 ===

4.2.17 readObject 方法
  • java.util.ArrayList#readObject 方法
  • 将输入流 ObjectInputStream 写入Collection
private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        elementData = EMPTY_ELEMENTDATA;

        // Read in size, and any hidden stuff
        s.defaultReadObject();

        // Read in capacity
        s.readInt(); // ignored

        if (size > 0) {
            // be like clone(), allocate array based upon size not capacity
            int capacity = calculateCapacity(elementData, size);
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            ensureCapacityInternal(size);

            Object[] a = elementData;
            // Read in all elements in the proper order.
            for (int i=0; i<size; i++) {
                a[i] = s.readObject();
            }
        }
    }

4.2.18 为什么elementData是transient的?

ArrayList变量表

  1. ArrayList在序列化的时候会调用writeObject,直接将size和element写入ObjectOutputStream;反序列化时调用readObject,从ObjectInputStream获取size和element,再恢复到elementData。
  2. 为什么不直接用elementData来序列化,而采用上诉的方式来实现序列化呢?原因在于elementData是一个缓存数组,它通常会预留一些容量,等容量不足时再扩充容量,那么有些空间可能就没有实际存储元素,采用上诉的方式来实现序列化时,就可以保证只序列化实际存储的那些元素,而不是整个数组,从而节省空间和时间。

=== 点击查看top目录 ===

4.2.19 toArray 方法
  • java.util.ArrayList#toArray() 方法
    public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
    }
  • java.util.Arrays#copyOf(T[], int) 方法
    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
  • java.util.Arrays#copyOf(U[], int, java.lang.Class<? extends T[]>) 方法
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }
  • java.lang.System#arraycopy
  • 底层是深复制
 public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);
  • List内部也是数组Array,复制的底层就是调用 System#arraycopy 将List内部数组复制成一个新的Object数组
    === 点击查看top目录 ===
4.2.20 size 方法
  • java.util.ArrayList#size 方法
    public int size() {
        return size;
    }

=== 点击查看top目录 ===

4.3 是否指定 capacity 带来的区别

private static void test01() {
    ArrayList<String> stringList = new ArrayList<>(100000000); // 162ms 
    ArrayList<String> stringList = new ArrayList<>(1); //  9000ms

    long begin = System.currentTimeMillis();

    for (int i = 0; i < 100000000; i++) {
        stringList.add("A");
    }

    long end = System.currentTimeMillis();
    System.out.println("ArrayList -> " + (end - begin));
}
  • 162ms VS 9000m ,原因就是内部的 copy 操作,每次扩容都会全量复制一次。

五、Vector 类

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
  • 在 ArrayList 基础上,所有方法加上 synchronized 。

=== 点击查看top目录 ===

六、CopyOnWriteArrayList 类

6.1 变量

变量 备注
final transient ReentrantLock lock = new ReentrantLock(); 写的时候加锁
private transient volatile Object[] array; 数组,存放元素,transient说明重写了 readObject 与 writeObject 方法,目的是为了不存储空数据

6.2 代码

  • 整体代码:
package java.util.concurrent;

public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

    /** The lock protecting all mutators */
    final transient ReentrantLock lock = new ReentrantLock();

    /** The array, accessed only via getArray/setArray. */
    private transient volatile Object[] array;
    ...
}
  • 查询方法相比 ArrayList 无任何改动。
  • 写入方法:
6.2.1 set 方法
  • java.util.concurrent.CopyOnWriteArrayList#set 方法
public E set(int index, E element) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            E oldValue = get(elements, index);

            if (oldValue != element) {
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len);
                newElements[index] = element;
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }
  • 注意
  1. 写的时候,先上 lock
  2. Arrays.copyOf 内部使用 native 方法进行复制
  3. 替换掉老数组
  4. 释放 lock

=== 点击查看top目录 ===

七、ImmutableList 类

  • 该类内的全部元素,一初始化便注定不能改变。
  • 元素不可改变的方法,任何一个写操作都会抛出 UnsupportedOperationException .
  • 抛出异常的方法
方法 描述
add(E e) throw new UnsupportedOperationException()
remove(Object object) throw new UnsupportedOperationException();
addAll(Collection<? extends E> newElements) throw new UnsupportedOperationException();
removeAll(Collection<?> oldElements) throw new UnsupportedOperationException();
retainAll(Collection<?> elementsToKeep) throw new UnsupportedOperationException();
clear() throw new UnsupportedOperationException();
package com.google.common.collect;

@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
public abstract class ImmutableList<E> extends ImmutableCollection<E>
    implements List<E>, RandomAccess {
}

=== 点击查看top目录 ===

7.1 构造方法 ImmutableList

ImmutableList() {}
  • default 类型的构造方法,说明只供同一个 package 下的使用,真正的初始化方法是 of

7.2 初始化方法 of


  @SuppressWarnings("unchecked")
  public static <E> ImmutableList<E> of() {  return (ImmutableList<E>) EMPTY; }
  public static <E> ImmutableList<E> of(E element) {  return new SingletonImmutableList<E>(element);  }
  public static <E> ImmutableList<E> of(E e1, E e2) {   return construct(e1, e2);   }
  public static <E> ImmutableList<E> of(E e1, E e2, E e3) {   return construct(e1, e2, e3);  }
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) {  return construct(e1, e2, e3, e4); }
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) { return construct(e1, e2, e3, e4, e5);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {return construct(e1, e2, e3, e4, e5, e6);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {return construct(e1, e2, e3, e4, e5, e6, e7);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { return construct(e1, e2, e3, e4, e5, e6, e7, e8);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);}
  public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);}
  public static <E> ImmutableList<E> of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {
    Object[] array = new Object[12 + others.length];
    array[0] = e1;
    array[1] = e2;
    array[2] = e3;
    array[3] = e4;
    array[4] = e5;
    array[5] = e6;
    array[6] = e7;
    array[7] = e8;
    array[8] = e9;
    array[9] = e10;
    array[10] = e11;
    array[11] = e12;
    System.arraycopy(others, 0, array, 12, others.length);
    return construct(array);
  }
  • 我还是没搞懂为什么要写那么多个 of 方法,直接下面这样不行吗???
  public static <E> ImmutableList<E> of( E e1,E... others) {
    Object[] array = new Object[1 + others.length];
    array[0] = e1;
    System.arraycopy(others, 0, array, 1, others.length);
    return construct(array);
  }

=== 点击查看top目录 ===

7.3 construct 方法

  private static <E> ImmutableList<E> construct(Object... elements) {
    return asImmutableList(checkElementsNotNull(elements));
  }
  • private 与 static 表明是一个静态私有构造方法,也就是该方法不会被外部调用。

7.4 checkElementsNotNull 方法

  • 该方法确保存入的元素 Element 不能为 null
  • ArrayList 、LinkedList 、Vector 允许null元素
static Object[] checkElementsNotNull(Object... array) {
    return checkElementsNotNull(array, array.length);
  }

  static Object[] checkElementsNotNull(Object[] array, int length) {
    for (int i = 0; i < length; i++) {
      checkElementNotNull(array[i], i);
    }
    return array;
  }

  // We do this instead of Preconditions.checkNotNull to save boxing and array
  // creation cost.
  static Object checkElementNotNull(Object element, int index) {
    if (element == null) {
      throw new NullPointerException("at index " + index);
    }
    return element;
  }
  • 虽然不能写,但是也就不能完全实现线程安全,毕竟 sort 方法还不是安全的。

=== 点击查看top目录 ===

八、LinkedList 类

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
  • 注意:这个类就不实现 RandomAccess 随机存储结构,而是

在这里插入图片描述

8.1 变量

变量名 备注
transient Node last; 元素数组
transient Node first; 元素数组
transient int size = 0 数组长度
  • 注意:变量都是 transient

=== 点击查看top目录 ===

8.2 方法 (public)

8.2.1 插入 add
方法名 备注
public boolean add(E e) 往最后面插入
public void add(int index, E element) 在某个 index 后插入 element
public void addFirst(E e) 往最前面插入
public void addLast(E e) 往最后面插入
public boolean addAll(Collection<? extends E> c) 插入某个Collection
public boolean addAll(int index, Collection<? extends E> c) 在固定 index 后面插入某个Collection
public boolean offer(E e) 往最后面插入
public boolean offerFirst(E e) 往最前面插入
public boolean offerLast(E e) 往最后面插入
public void push(E e) 往最前面插入addFirst(e);
  • add = offer 插最后 ,push 插开头

=== 点击查看top目录 ===

8.2.2 删除 remove
方法名 备注
public E removeFirst() 摘掉第一个
public E removeLast() 摘掉最后一个
public E remove(int index) 移除掉某个 index 下的element
public boolean remove(Object o) 移除掉某个元素
public E remove() 拉出第一个元素(要remove,遇 null 抛Exception)
public boolean removeFirstOccurrence(Object o) remove(o);
public boolean removeLastOccurrence(Object o) 从后往前面删
public E poll() 拉出第一个元素(要remove,遇 null 返回 null)
public E pollFirst() 拉出第一个元素(要remove,遇 null 返回 null)
public E pollLast() 拉出最后一个元素(要remove,遇 null 返回 null)
public E pop() pop出第一个元素(要remove,遇 null 抛Exception) removeFirst();
  1. remove = pop 遇 null 抛出 Exception
  2. poll 遇 null 返回 null

=== 点击查看top目录 ===

8.2.3 设置 set
方法名 备注
public E set(int index, E element) 设置 index 下面的 Element

=== 点击查看top目录 ===

8.2.4 get 查询
方法名 备注
public E get(int index) 获取某个 index 下的 Element
public E getFirst() 拿到第一个Element
public E getLast() 拿到最后一个 Element
public E element() 拿到第一个元素 (不remove,遇 null 抛Exception)
public E peek() 拿到第一个元素(不remove,遇 null 返回 null)
public E peekFirst() 拿到第一个元素(不remove,遇 null 返回 null)
public E peekLast() 拿到最后一个元素(不remove,遇 null 返回 null)

=== 点击查看top目录 ===

8.2.5 其他操作
方法名 备注
public int indexOf(Object o) 查找某个元素存在的下标,找不到返回 -1
public int lastIndexOf(Object o) 查找某个元素存在的下标(从后面开始找),找不到返回 -1
public boolean contains(Object o) 是否包含某个 Element
public int size() collection 长度
public void clear() 清除元素
public ListIterator listIterator(int index) 拿到 ListItr
public Iterator descendingIterator() 拿到从后往前的 Iterator
public Object clone() 克隆,浅复制 shallow copy
public Object[] toArray() 转成数组
public Spliterator spliterator() 拿到从前往后的 Iterator

=== 点击查看top目录 ===


九、番外篇

下一章节:【Java Collection】Queue 剖析(四)

上一章节:【Java Collection】List 剖析(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章