前言:HashMap、Hashtable、TreeMap都是java.util.Map接口的实现类,都是通过key-value存储。不同的是,TreeMap同时又实现了SortMap接口,能够把它保存的记录根据键排序。WeakHashMap是HashMap的一个子类。
HashMap对比Hashtable、ConcurrentHashMap:
HashMap是Hashtable的轻量级实现有如下区别:
①HashMap可以存储一条key为null的记录,而Hashtable不允许。
②Hashtable、ConcurrentHashMap是线程安全的,而HashMap、TreeMap不是线程安全的。
③HashMap去掉了Hashtable中的contains方法(容易引起歧义),改成了containsValue和containsKey。
④Hashtable使用Enumeration,HashMap使用Iterator。
⑤Hashtable中,hash数据的默认大小是11,增长方式是 old*2+1。而HashMap中默认大小是16,且必须是2的指数。
⑥hash值的使用不同,Hashtable字节使用对象的hashCode。
TreeMap因为实现了SortMap接口,所以取出来的记录是排序后的键值对,如果需要按自然顺序或是自定义顺序排序,可以使用TreeMap。三者中使用最多的是HashMap,HashMap里面存入的键值对在取出时没有固定的顺序,是随机的。
WeakHashMap与HashMap类似,不同之处在于,WeakHashMap中的Key采用的是“弱引用”,只要key不在倍外部引用,它就可以被垃圾回收器回收。而HashMap中的key采用“强引用”,当HashMap中的key没有被外部引用时,只有在这个key从HashMap中删除后,才可以被垃圾回收器回收。
ConcurrentHashMap与Hashtable的区别:
二者都是线程安全的,但是由区别。区别在于他俩加锁的范围不同,Hashtable 对整张Hash表进行加锁,而ConcurrentHashMap将Hash表分为16桶(segment),每次只对需要的桶加锁。
常见面试题:
1、在Hashtable上下文中,同步指的是什么?
答:同步以为着一个时间点只能有一个线程可以修改 hash 表,任何线程在执行 Hashtable 的更新操作前都需要获取对象锁,其他线程等待锁的释放。
2、如何实现HashMap的同步?
答:方式①: HashMap 可以通过 Map map = Collections.synchronizedMap(new HashMap()); 来达到同步的效果。该方法返回一个同步的Map,该Map封装了底层的 HashMap 的所有方法,使得底层的 HashMap 即使在多线程的环境中也是安全的。
方式②: Map<K, V> map = new ConcurrentHashMap<K, V>( );
扩展:
Collections类提供了synchornizedXxx( )方法,可以将指定的集合包装成线程同步的集合。比如,
List list = Collections.synchronizedList( new ArrayList( ) );
Map map = Collections.synchronizedMap( new HashMap( ));
Set set = Collections.synchronizedSet( new HashSet( ));