List实现类的一些源码理解

  • for, forEach, Iterator 在遍历上的效率区别
    forEach 在遍历Obejct时编译后的源码是IteratorforEach在遍历基本类型时编译后的源码是for循环。
    遍历ArrayList的时候 forEach, Iterator 差不多, for比这两个快一些。遍历LinkedList的时候速度: forEach, Iterator >> for

  • AbstractList类有一个modCount字段,每次表结构发生修改时+1,用来确保简单的线程安全,迭代器在遍历时如果发现modCount发生修改时抛出 ConcurrentModificationException异常。

ArrayList

  • ArrayList集成AbastractList并实现RandomAcessSerializableCloneable三个接口。

  • 默认容量为10,最大容量Integer.MAX_VALUE - 8。

  • 数组存储元素,并不进行序列化。通过将 elementData 字段标记为 transient,在序列化过程中,该字段将被忽略,只序列化 ArrayList 对象中的元素和其他必要的状态信息。在反序列化时,ArrayList 对象会重新创建一个默认大小的数组,并将反序列化的元素放入该数组中。

transient Object[] elementData; // non-private to simplify nested class access
  • 每次需要扩容时增加到1.5倍,
     - - - - - - - - - - - - - - - - - - - - - - - - - - - 
    触发扩容
    if (minCapacity - elementData.length > 0)
            grow(minCapacity);
	- - - - - - - - - - - - - - - - - - - - - - - - - - - 
	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);
    }

扩容时使用Arrays.copyOf(),和addAll以及remove等时会使用 System.arrayCopy。Arrays.copyOf()底层由System.arrayCopy实现,区别在于System.arrayCopy是从源数组向目标数组拷贝,没有返回值。Arrays.copyOf()创建新数组对象并拷贝。二者的都是浅拷贝

LinkedList

LinkedList是一个双向链表,可以当做双端队列使用。源码比较简单。注意到一个地方是在removeALL的时候会断开所有节点的前后链接,清除节点之间的所有链接在某种程度上是“不必要的”,但是对于分代垃圾回收来说,如果废弃的节点跨越多个代,这样做是有帮助的 ,即使存在可访问的迭代器,也可以确保释放内存。

Vector

Vector极少使用,如今为了线程安全通常会用copyOnWriteArrayList。

  • COW意思就是大家共同去访问一个资源,如果有人想要去修改这个资源的时候,就需要复制一个副本,去修改这个副本,完成后再替换。避免影响读。

  • COW两个主要的属性

独占锁ReentrantLock,
多线程运行的情况下,只有一个线程会获得这个锁,只有释放锁后其他线程才能获得。

final transient ReentrantLock lock = new ReentrantLock();

存放数据的数组,关键是被volatile修饰了,被volatile修饰,
就保证了可见性,也就是一个线程修改后,其他线程立即可见。

private transient volatile Object[] array;
  • 添加操作(修改删除类似)
public boolean add(E e) {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        // 获取原来的数组
        Object[] elements = getArray();
        // 原来数组的长度
        int len = elements.length;
        // 创建一个长度+1的新数组,并将原来数组的元素复制给新数组
        Object[] newElements = Arrays.copyOf(elements, len + 1);
        // 元素放在新数组末尾
        newElements[len] = e;
        // array指向新数组
        setArray(newElements);
        return true;
    } finally {
        lock.unlock();
    }
}

Stack

  • stack继承vector,四个常用操作push pop peek search 都加了syncronized(push使用addElement完成)。
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值