您的位置:首页 > 职场人生

Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

2016-12-12 23:00 579 查看
2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash……系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度、唯品会、58同城、新浪微博、趣分期、美团点评等都在1、2……面的时候被问过无数次,都问吐了&_&,其他公司笔试的时候,但凡有Java的题,都有集合相关考点,尤其hash表……现在总结下。

2016-12-15 更新:Java 8 对 HashMap 的改进

2016-12-12 整理jdk 1.8之前的HashMap实现

2016-12-15 更新:Java 8 对 HashMap 的改进

如果说Java的hashmap是数组+链表,那么JDK 8之后就是数组+链表+红黑树组成了hashmap。之前的实现机制和原理在下面12-12期整理过,这次只说下新加的红黑树机制。

在之前谈过,如果hash算法不好,会使得hash表蜕化为顺序查找,即使负载因子和hash算法优化再多,也无法避免出现链表过长的情景(这个概论虽然很低),于是在JDK1.8中,对hashmap做了优化,引入红黑树。具体原理就是当hash表中每个桶附带的链表长度默认超过8时,链表就转换为红黑树结构,提高HashMap的性能,因为红黑树的增删改是O(logn),而不是O(n)。

红黑树的具体原理和实现以后再总结。

主要看put方法实现

// synchronizedMap方法
public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
return new SynchronizedMap<>(m);
}
// SynchronizedMap类
private static class SynchronizedMap<K,V>
implements Map<K,V>, Serializable {
private static final long serialVersionUID = 1978198479659022715L;

private final Map<K,V> m;     // Backing Map
final Object      mutex;        // Object on which to synchronize

SynchronizedMap(Map<K,V> m) {
this.m = Objects.requireNonNull(m);
mutex = this;
}

SynchronizedMap(Map<K,V> m, Object mutex) {
this.m = m;
this.mutex = mutex;
}

public int size() {
synchronized (mutex) {return m.size();}
}
public boolean isEmpty() {
synchronized (mutex) {return m.isEmpty();}
}
public boolean containsKey(Object key) {
synchronized (mutex) {return m.containsKey(key);}
}
public boolean containsValue(Object value) {
synchronized (mutex) {return m.containsValue(value);}
}
public V get(Object key) {
synchronized (mutex) {return m.get(key);}
}

public V put(K key, V value) {
synchronized (mutex) {return m.put(key, value);}
}
public V remove(Object key) {
synchronized (mutex) {return m.remove(key);}
}
// 省略其他方法
}


View Code
从源码中看出 synchronizedMap()方法返回一个SynchronizedMap类的对象,而在SynchronizedMap类中使用了synchronized来保证对Map的操作是线程安全的,故效率其实也不高。

为什么HashTable的默认大小和HashMap不一样?

前面分析了,Hashtable 的扩容方法是乘2再+1,不是简单的乘2,故hashtable保证了容量永远是奇数,结合之前分析hashmap的重算hash值的逻辑,就明白了,因为在数据分布在等差数据集合(如偶数)上时,如果公差与桶容量有公约数 n,则至少有(n-1)/n 数量的桶是利用不到的,故之前的hashmap 会在取模(使用位与运算代替)哈希前先做一次哈希运算,调整hash值。这里hashtable比较古老,直接使用了除留余数法,那么就需要设置容量起码不是偶数(除(近似)质数求余的分散效果好)。而JDK开发者选了11。

JDK 8对HashMap有了什么改进?说说你对红黑树的理解?

参考更新的jdk 8对hashmap的的改进部分整理,并且还能引申出高级数据结构——红黑树,这又能引出很多问题……学无止境啊!

临时小结:感觉针对Java的hashmap和hashtable面试,或者理解,到这里就可以了,具体就是多写代码实践。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: