经典面试题总结:
-
hashmap具备哪些特点?
-
Java7和Java8的区别?
-
哈希表如何解决Hash冲突?
-
为什么 HashMap 中 String、Integer 这样的包装类适合作为 key 键
-
HashMap 中的 key若 Object类型, 则需实现哪些方法?
-
hash的计算规则?
-
默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?
-
为什么会选择8作为链表转红黑树的阈值?
面试题解析:
hashmap具备那些特点?
Java7和Java8的区别?
jdk7 数组+单链表 jdk8 数组+(单链表+红黑树)
jdk7 链表头插 jdk8 链表尾插
头插: resize后transfer数据时不需要遍历链表到尾部再插入
头插: 最近put的可能等下就被get,头插遍历到链表头就匹配到了
头插: resize后链表可能倒序; 并发resize可能产生循环链
jdk7 先扩容再put jdk8 先put再扩容 (why?有什么区别吗?)
jdk7 计算hash运算多 jdk8 计算hash运算少(http://www.jasongj.com/java/concurrenthashmap/#寻址方式-1)
jdk7 受rehash影响 jdk8 调整后是(原位置)or(原位置+旧容量)
哈希表如何解决Hash冲突?
为什么 HashMap 中 String、Integer 这样的包装类适合作为 key 键
HashMap 中的 key若 Object类型, 则需实现哪些方法?
hash计算规则
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
取出key的hashcode,右移16位,然后取异或 : int是4个字节,也就是32位,我们右移16位也即是把高位的数据右移到低位的16位,然后做异或,那就是把高位和低位的数据进行重合,同时保留了低位和高位的信息
默认初始化大小是多少?为啥是这么多?为啥大小都是2的幂?
初始化大小为1<<4, resize时扩容为原来的两倍;
HashMap的容量为什么是2的n次幂,和这个(n - 1) & hash的计算方法有着千丝万缕的关系,符号&是按位与的计算,这是位运算,计算机能直接运算,特别高效,按位与&的计算方法是,只有当对应位置的数据都为1时,运算结果也为1,当HashMap的容量是2的n次幂时,(n-1)的2进制也就是1111111***111这样形式的,这样与添加元素的hash值进行位运算时,能够充分的散列,使得添加的元素均匀分布在HashMap的每个位置上,减少hash碰撞。
为什么会选择8作为链表转红黑树的阈值?
根据泊松分布,在负载因子默认为0.75的时候,单个hash槽内元素个数为8的概率小于百万分之一,所以将7作为一个分水岭,等于7的时候不转换,大于等于8的时候才进行转换,小于等于6的时候就化为链表。