java集合框架笔记

1、ArrayList 与 LinkedList

  都不保证线程安全。

   Arraylist 底层使用的是Object数组;LinkedList 底层使用的是双向循环链表。

  LinkedList 不支持高效的随机元素访问,而ArrayList 实现了RandmoAccess 接口,所以有随机访问功能。快速随机访问就是通过元素的序号快速获取元素对象(说白了就是get(int index)方法)。

  再回去看看ArrayList源码,很简单(add方法的扩容判断)。

2、ArrayList 与 Vector(很像)

  Vector类的所有方法都是同步的。一个线程访问Vector的话要在同步操作上耗费大量的时间。

3、HashMap

  jdk 1.8以前HashMap由数组+链表组成的(“链表散列”),链表部分主要为了解决哈希冲突,时间复杂度取决于链表的长度,为 O(n)。

  1.8之后当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。

  红黑树就是为了解决二叉搜索树的缺陷,因为二叉搜索树在某些情况下会退化成一个线性结构(最少两次平衡操作使二叉搜索树保持相对平衡状态)。

  HashMap的长度都是2的幂次方,在于为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,算法上则采用取余操作。取余(%)操作中如果除数是2的幂次方,等价于与其除数减一的与(&)操作(9%4=1 equal 1001&11=1)。 并且采用二进制位操作 &,相对于%能够提高运算效率。

4、HashMap 与 HashTable

  HashMap 是非线程安全的,HashTable 是线程安全的。

  HashTable 基本被淘汰,要保证线程安全的话就使用 ConcurrentHashMap。

  HashTable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。

  在HashMap 中,null 可以作为键,任何键所对应的值也可以为 null。但是在 HashTable 中 put 进的键值为null时抛出 NullPointerException。

5、ConcurrentHashMap

  低层数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。

  实现线程安全的方式:

  1.7以前,ConcurrentHashMap 是由 Segment 数组 和 HahEntry 数组结构组成。一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。

  1.8后synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生同步。

猜你喜欢

转载自www.cnblogs.com/LinsenLi/p/9595400.html