外观
集合框架2个工具类
集合框架2个工具类
Arrays
Collections
3.Map
HashMap1.8以后的实现。
默认hash数组的长度是16
默认的加载(填充)因子是0.75(桶数组的填满程度)
capacity 即容量,默认16。
loadFactor 加载因子,默认是0.75
threshold 阈值。阈值=容量*加载因子。默认12。当元素数量超过阈值时便会触发扩容。
一般情况下,当元素数量超过阈值时便会触发扩容。每次扩容的容量都是之前容量的2倍。
扩容时机 hash数组的长度*加载(填充)因子被使用,进行扩容
jd8 hahsmap与jdk7的区别?
数据结构上的区别
- 1.JDK7中的数据结构主要是:数组+链表,数组和链表的节点的实现类是Entry类 2.JDK8中的数据结构主要是:数组+链表/红黑树,当链表的元素个数大于等于8的时候转为红黑树,元素个数小于等于6时,红黑树结构还原成链表,数组和链表的节点的实现类是Node类
Hash值的计算区别
- JDK7:h^ =(h>>>20)^(h>>>12) return h ^(h>>>7) ^(h>>>4); 2.JDK8:(key==null)?0:(h=key.hashCode())^(h>>>16) 剖析:
.链表数据插入的区别
- 1.JDK7:使用的是头插入法,扩容后与原位置相反(resize会导致环形链表) 2.JDK8:使用的尾插法,扩容后位置与原链表相同
扩容机制的不同 1.JDK7扩容条件:元素个数 > 容量(16) * 加载因子 (0.75) && 插入的数组位置有元素存在 2.JDK8扩容条件 :元素个数 > 容量 (16) * 加载因子(0.75) 剖析:
HashMap和Hashtable的区别
对外提供的接口不同
Hashtable比HashMap多提供了elments() 和contains() 两个方法。
elments() 方法继承自Hashtable的父类Dictionnary。elements() 方法用于返回此Hashtable中的value的枚举。
contains()方法判断该Hashtable是否包含传入的value。它的作用与containsValue()一致。事实上,contansValue() 就只是调用了一下contains() 方法。
继承的父类不同
- 。HashMap是继承自AbstractMap类,而HashTable是继承自Dictionary类。不过它们都实现了同时实现了map、Cloneable(可复制)、Serializable(可序列化)这三个接口
线程安全性不同
Hashtable是线程安全的,它的每个方法中都加入了Synchronize方法。在多线程并发的环境下,可以直接使用Hashtable,不需要自己为它的方法实现同步
HashMap不是线程安全的,在多线程并发的环境下,可能会产生死锁等问题。具体的原因在下产生时间
Hashtable是java一开始发布时就提供的键值映射的数据结构,而HashMap产生于JDK1.2。
对Null key 和Null value的支持不同
- Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注释中有说明。
- HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,可能是 HashMap中没有该键,也可能使该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
遍历方式的内部实现上不同
- Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式
map集合的遍历方式
1.entrySet()方法获取一个Map元素的Set集合,对Set集合进行遍历使用get(index).get
2.keySet()方法获取一个键值的Set集合遍历key的Set集合使用key.get(key)方法获取对应的值
HashMap的Iterator是fail-fast迭代器。当有其它线程改变了HashMap的结构(增加,删除,修改元素),将会抛出ConcurrentModificationException。不过,通过Iterator的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。
快速失败工作模式
- 进入快速失败模式后,只要不通过迭代方式就会快速失败,java.util.ConcurrentModificationException