HashMap
知识点1 :怎么求的Hash,通过对象的Hashcode值 高16位保持不变 低16位与高16位异或求值 得到Hash值
知识点2 : Hash碰撞 拥有相同的Hash值产生碰撞 新版HashMap会把数据放在此下标的链表里 放在表尾 链表过长会采用红黑树
知识点3 : Index的计算 Hash & (n-1)n为当前bucket的size bucket是一个数组
知识点4 : bucket扩容时 重新计算 Index = Hash &(n-1)n为新的数组size 值还是会均匀的分布在bucket数组当中
知识点5 : key value可以为null
知识点6: :reHash时 判断新增的位是否为0 0就不变 , 1 移动两位
知识点7 :HashMap 当自定义对象时需要重写equals方法为什么需要重写hashcode
?因为不同的hashcode可能会返回一样的index下标 ,然后判断equals(默认地址比较)的时候,可能会相同造成覆盖问题,这种情况符合项目的话,其实是可以不重写的,但是大多数情况下需要重写。
衍生知识点 : 如何保证线程安全,Collections.synchronizedMap()方法来得到一个同步的HashMap,HashTable,ConcurrentHashMap,性能:ConcurrentHashMap > SynchronizedMap > Hashtable。
jdk1.8 采用CAS + synchronized 正常情况下hash不冲突时 put 采用CAS插入,冲突时会同步锁住。扩容操作时的线程安全,扩容时也允许查找数据。
get 基本和HashMap类似。
ArrayList
知识点1: 结构比较简单,大于现有数组长度 扩容 实现可变size的动态数组
知识点2: 核心是扩容机制,默认最大容量10,当达到这个数时会扩大到1.5倍。
LinkedList
知识点1 : 双向链表实现。查找慢
TreeMap
知识点1: 红黑树 树的中序遍历保证有序
LinkedHashMap
知识点1: 继承了HashMap 依靠双向链表实现顺序访问
知识点2: 有两种模式:顺序模式和访问模式,顺序模式按照插入顺序输出,访问模式按照访问的时间,访问中间的元素会放到双向链表的最后。
访问模式代码
void afterNodeAccess(Node<K,V> e) { // move node to last
LinkedHashMapEntry<K,V> last;
if (accessOrder && (last = tail) != e) {
LinkedHashMapEntry<K,V> p =
(LinkedHashMapEntry<K,V>)e, b = p.before, a = p.after;
p.after = null;
if (b == null)
head = a;
else
b.after = a;
if (a != null)
a.before = b;
else
last = b;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
tail = p;
++modCount;
}
}
知识点3: put的时候会调用linkNodeLast
加到最后
private void linkNodeLast(LinkedHashMapEntry<K,V> p) {
LinkedHashMapEntry<K,V> last = tail;
tail = p;
if (last == null)
head = p;
else {
p.before = last;
last.after = p;
}
}
网友评论