Collection 接口是 Set, List, Queue 接口的父接口, 申明了多数集合常用方法,包括 add(),remove(),contains(),size(),iterator() 等
List 有序可重复,可以通过 Iterator 遍历元素,可通过 get(int index) 下标访问元素
arrayList 底层是数组,线程不安全,随机访问元素很快,插入删除元素很慢,适合下标访问,超出长度存数据时需要新建数组,然后将老数组的数据拷贝到新数组,如果不是尾部插入数据还会涉及元素的移动,使用尾插法并指定初始容量可以提升性能
Vector 是 ArrayList 的线程安全版本,性能比 ArrayList 要低,现在已经很少使用
linkedList 底层是链表,插入删除快,查询慢,遍历时应该用 Iterator,而不是 for 循环,循环体内通过 get(i) 取得某一元素时需要对 list 重新遍历,性能消耗较大
Set 无序去重(需要实现 equals()), 只能通过 Iterator 遍历元素
hashset 查询速度快(需要实现 hashcode() )
linkedHashSet 插入顺序保存元素(底层链表维持插入顺序),查询速度跟 hashset 差不多(需要实现 hashcode())
treeset 有序(必须实现 comparable 接口),底层为树
sortedset 比较函数排序
Queue 用于保存将要执行的任务列表
LinkedList 实现了 Queue 接口,可以实现先进先出的队列
PriorityQueue 用来创建自然排序的优先级队列
Map 键不可重复(需要实现 equals())
----------------------------
HashMap 线程不安全,查询快,底层为数组 + 链表
jdk8 以后当链表高度为8,数组长度超过64,链表转变为红黑树,低于6红黑树转为链表
根据 key 的 hash 值二次 hash 后对数组长度取模对应数组下标,如果下标位置没存元素则存入数组,如果下标位置有元素,进行 equals 比较,相同则覆盖该元素,不同则插入链表
允许 key 或 value 为 NULL
key 为 null 时,存在下标 0 的位置
----------------------------
HashMap 扩容机制
----------------------------
根据扩容因子生成更大的新数组,遍历老数组中每个位置上的链表或红黑树上的每个元素,重新计算每个元素的下标,并添加到新数组中,如果某个位置下的元素个数没有超过8就用链表存储,超过8则生成一棵红黑树存储该位置的元素,转移完所有元素之后,将新数组赋值给 HashMap 的 table 属性
----------------------------
HashMap 的 Put 方法
----------------------------
1.通过 key 的 hashcode() 算出数组下标
2.如果数组下标位置为空,则将 key 和 value 封装为 Entry/Node 对象,放入该位置
3.如果下标位置不为空
先判断当前位置的 node 类型,如果是红黑树,判断红黑树是否存在当前 key, 如果存在则覆盖 value,不存在则将 key 和 value 封装成一个红黑树节点并加入红黑树
如果是链表,则判断是否存在当前 key, 存在就覆盖 value, 不存在则尾插法加入链表,如果链表节点个数大于等于8就将该链表转为红黑树, 最后判断是否需要扩容
----------------------------
ConcurrentHashMap
----------------------------
synchronized + CAS + Node + 红黑树
扩容或 hash 冲突时,使用 synchronized 锁链表的 head 节点,不影响其他元素的读写,Node 的 val 和 next 都用 volatile 修饰,读写线程互相可见,数组用 volatile 修饰,扩容时读线程可见
查找,替换,赋值都使用 CAS,
当某个线程 put 时,发现没有正在进行扩容,就添加 key-value,再判断是否超过阈值,超过就扩容
当某个线程 put 时,发现正在进行扩容,就参与扩容,扩容时先生成一个新数组,将原数组分成多组,多个线程参与元素转移工作
----------------------------
HashTable 线程安全,很多方法都加了 synchronized,性能不好,推荐用 concurrentHashMap
linkedhashmap 插入顺序保存键(底层链表维持插入顺序),保留 hashmap 的查询速度(需要实现 hashcode())
treemap 键有序(必须实现 comparable 接口),底层为树