集合框架源码阅读

223 阅读2分钟

一、ArrayList源码解读

  1. 实现原理,内部由一个数组构成。关键属性:数组-容量、元素个数、修改编号(fast-fail机制)
  2. 初始化是一个空数组,默认容量为10,扩容机制是新增加当前容量的一半,如果扩容后的值小于最小容量(size+addAll.size).
  3. fast-fail机制:快速失效系统一种可以立即报告任何可能表明故障的情况的系统.(modCount属性),新增和删除都会增加modCount,修改数组中的对象modCount不会修改。
  4. 迭代器:实现是通过游标来控制,获取数据还是原来的数组,容器实现Iterator接口的提供同样的访问方式,这就是迭代器模式的实现。

二、LinkList 源码解读

  1. 实现原理:内部有一个头结点和尾结点,结点内部结构是由结点对象、上一个结点、下一个结点组成。
public class LinkedList<E>{
    
    transient int size = 0;

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first;

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last;
        
    /**
     * 结点数据结构
     */
    private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
}
  1. 实现双向链表功能
  2. 因为是链式存储,无需扩容。
  3. 迭代器:同样实现

三、ArrayList与LinkedList的实现和区别

  1. 实现方式、应用场景、扩容方式、大小对比情况
实现方式 应用场景 扩容方式 最大长度
ArrayList 动态数组 读取 1.5倍 2^32-8
LinkedList 链表 插入、删除 正常插入末尾 无限大
  1. 时间复杂度对比
读取 插入删除
ArrayList O(1):根据下表读取 O(n):插入或删除需要将之后的所有元素后移或迁移
LinkedList O(n):循环遍历 O(1):只需要制定的结点进行插入或删除

四、HashMap、Hashtable、ConcurrentHashMap

  1. HashMap的key和value可以为null,Hashtable、ConcurrentHashMap的key和value不能为空,为什么jdk要这样设计呢?

ConcurrentHashmap和Hashtable都是支持并发的,这样会有一个问题,当你通过get(k)获取对应的value时,如果获取到的是null时,你无法判断,它是put(k,v)的时候value为null,还是这个key从来没有做过映射。HashMap是非并发的,可以通过contains(key)来做这个判断。而支持并发的Map在调用m.contains(key)和m.get(key),m可能已经不同了。