c++ list 修改_一线码农java系列之List

List概述

List属于Java集合系统一员。List本身是一个interface继承了Collection接口。List中定义各种对集合的操作,List的具体实现包括ArrayList、Vector和LinkedList等,List所处位置如下图所示(非完整图):

28e8ce0b8a71e05aa3562c2b4ec1a3de.png

List提供了特殊迭代器ListIterator,该迭代器提供了双向迭代访问集合的功能。 接口方法如下所示:

ListIterator<E> listIterator();

ListIterator<E> listIterator(int index);

List具体实现类

List实现类主要包括ArrayList、Vector和LinkedList。

ArrayList

ArrayList类关系图如下所示:

28289c8a20ba679f8b83137e818ee7a4.png

注意:

其中RandomAccess接口只是个标记表面该接口的具体实现可以支持随机访问,RandomAccess本身不定义任何东西;

Cloneable接口作为支持field-for-field拷贝标记,如果实现该接口,会报”CloneNotSupportedException”错误;

Serializable序列号接口标记;serialVersionUID建议显示指定,因为不同的java编译器自动生成serialVersionUID的时候可能不一样,会报”InvalidClassException”错误

ArrayList底层数据结构为数组,因此支持随机访问

Object[] elementData

contain方法是通过遍历实现,因此时间复杂度线性的

扩容机制

ArrayList的扩容机制相对来说比较简单,如下所示:

/**

     * Increases the capacity to ensure that it can hold at least the

     * number of elements specified by the minimum capacity argument.

     *

     * @param minCapacity the desired minimum capacity

     */

    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);

    }

通常情况下一次扩容后大小为原来的三倍。

fail-fast

fail-fast是Java集合的一种错误检测机制。在用迭代器对List进行遍历的时候,如果有其它线程对List进行了结构性修改,则会报: ConcurrentModificationException。

不要在foreach中对元素进行remove/add操作。如果需要remove元素请用iterator方式,并发操作的时候需要加锁。

modCount

记录对list进行结构化修改的次数,所谓结构化修改(Structurally modified)即改变list大小的操作

removeAll()

删除指定的集合元素

方法定义:

public boolean removeAll(Collection<?> c)

底层调用batchRemove方法,batchRemove方法基本思想就是会一边遍历List一边把不在指定集合中的原始往前挪,源代码如下所示:

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.

        if (r != size) {

            System.arraycopy(elementData, r,

                             elementData, w,

                             size - r);

            w += size - r;

        }

        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;

}

获取子串subList

由源码可知获取子串是由定义的SubList类实现,其实获取并未重新开辟空间,引用的还是原始的数据;

public List<E> subList(int fromIndex, int toIndex) {

    subListRangeCheck(fromIndex, toIndex, size);

    return new SubList(this, 0, fromIndex, toIndex);

}

Spliterator可拆分迭代器

Spliterator用于遍历和对源数据进行分区,源数据可以是数组,集合,IO通道或者是生成函数;Spliterator可以单独遍历元素(tryAdvance)或者批量遍历元素(forEachRemaining)

主要方法

1) trySplit

并行操作时,可以通过trySplit方法将spliterator划分为另外一个spliterator

2) characteristics

包括spliterator特性,特性包括:DISTINCT, SORTED,SIZED,NOTNULL, IMMUTABLE,CONCURRENT,SUBSIZED

该特性被定义为4个字节的int类型,如:

public static final int DISTINCT = 0x00000001;

public static final int SORTED = 0x00000004;

public static final int SIZED = 0x00000040;

具体使用时候通过按位与判断数据所具有的特性,如ArrayListSpliterator中该方法定义如下:

public int characteristics() {

    return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED;

}

3)estimateSize

评估剩余访问元素的大小

ArrayListSpliterator

非线程安全

ArrayList本身是非线程安全的。

Vector

Vector和ArrayList实现类似,底层数据结构也是数组,Vector是线程安全的而ArrayList是非线程安全的;Vector方法由synchronized修饰,从而保证线程安全;

扩容策略

当变量capacityIncrement <= 0时候 扩容为原先数组大小的两倍,否则扩容capacityIncrement

LinkedList

LinkedList双端链表,实现了List和deque接口,非线程安全,如果要支持线程安全,需要从外部进行保证,如可以通过Collections.sychronizedList进行封装,如下所示:

List list = Collections.synchronizedList(new LinkedList());

linkedList在集合系统中所处位置如下所示:

5112956ce98c9b77152dd603457d928b.png

ListIterator迭代器

ListIterator继承Iterator实现了List的迭代访问,ListIterator主要定义了hasNext(), next(), hasPrevious(), previous()等一系列方法,LinkedList定义内部累ListItr改类实现ListIterator接口,通过ListItr达到链表双向访问的目的

toArray方法

public <T> T[] toArray(T[] a) {

    if (a.length < size)

        a = (T[])java.lang.reflect.Array.newInstance(

                            a.getClass().getComponentType(), size);

    int i = 0;

    Object[] result = a;

    for (Node<E> x = first; x != null; x = x.next)

        result[i++] = x.item;

    if (a.length > size)

        a[size] = null;

    return a;

}

其它

Arrays.copyOf

Arrays.copyOf(T[] original, int newLength) 在调用的时候会创建新的数组,底层实际上是通过调用System.arraycopy实现的

Arrays.sort

底层为归并排序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值