java集合与底层实现(中)

集合 List

特点:有序(存储顺序和取出顺序一致),可重复
ArrayLIst 数据结构是数组,线程不安全
LinkedList 数据结构是链表,线程不安全(双向链表方便实现往前遍历)
Vector 数据结构是数组,线程安全
copyOnWriteList 并发容器,线程安全(COW设计模式)

ArrayList解析

  • ArrayList底层为一个数组,内部有扩容的概念,初始容量为10,每次扩容增加原先容量的一半(1.5倍)实现了”动态“增长
  • ArrayList是基于动态数组实现的,在增删的时候,需要数组的拷贝复制
  • 删除元素时不会减少容量,若希望减少则调用trimToSize()
  • 它不是线程安全的,能存放null
  1. Add(E e)方法
    首先检查一下数组的容量是否足够,足够则直接添加,不够扩容,扩容到原来的1.5倍,第一次扩容后,如果容量还是小于minCapacity,就将容量扩容为minCapacity
  2. Add(int index,E e)
    检查角标是否越界,空间检查,如果有需要进行扩容,调用arraycopy()来进行插入(在高性能的jvm中,会对这种intrinsic method进行特殊优化处理,达到高效执行数组拷贝)
  3. get(int index)以及set(int index,E e)
    检查角标,返回元素/替代元素(会返回旧值)
  4. remove(int index)
    检查角标,计算出需要移动的个数,并移动、删除元素,elementData[—size] = null; 设置为null,让GC回收

Vector

  • Vector底层也是数组,它是线程安全
  • 如果想要ArrayList实现同步,可以使用Collections的方法:List list = Collections.synchronizedList(new ArrayList(…));,就可以实现同步
  • Vector扩容原来的1倍,arrayList扩容原来的0.5倍

LinkedLIst

  • 底层是双向链表
  • linkedList实现了deque接口,我们可以操作linkedList像操作队列和栈一样
  1. add(E e)方法
    往链表最后添加元素
final node temp = last;
final newNode = new Node();
last = newNode;
l.next = newNode;
Size++;
  1. remove(Object o)
    双向链表删除数据
  2. get(int index) 、set(int index,E e)
    通过传入的下标与size对比,下标小于长度的一半,就从头遍历,否则从尾遍历

copyOnWriteList

1.Hashtable、Vector加锁的粒度大(直接在方法声明处使用synchronized)
2.ConcurrentHashMap、CopyOnWriteArrayList加锁粒度小(用各种的方式来实现线程安 全,比如我们知道的ConcurrentHashMap用了cas锁、volatile等方式来实现线程安全…)
3.JUC下的线程安全容器在遍历的时候不会抛出ConcurrentModificationException异常

  • CopyOnWriteArrayList是线程安全容器(相对于ArrayList),底层通过复制数组的方式来实现。
  • CopyOnWriteArrayList在遍历的使用不会抛出ConcurrentModificationException异常,并且遍历的时候就不用额外加锁
  • 元素可以为null

猜你喜欢

转载自blog.csdn.net/qq_36741161/article/details/88429160
今日推荐