天天看点

HashMap , HashTable , ConcurrentHashMap 源码比较__v1.0

                   首先,hashmap , hashtable 与 concurrenthashmap 里面用的 都是 数组(node<k,v>[] table; 与 entry<?,?>[] table;),而且它们都是 transient 的,对于 transient ,效果如下:

                              1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

                              2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被        transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现serializable接口。

                              3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

                        且  concurrenthashmap 中的table同时被声明为 volatile,意义如下:

                                   1)一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。

                                   2)volatile一般情况下不能代替sychronized,因为volatile不能保证操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++,volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。如果配合java 5增加的atomic wrapper classes,对它们的increase之类的操作就不需要sychronized。 

                           hashmap 与 concurrenthashmap 继承的是 abstractmap,而 hashtable 继承的是 dictionary;它们是有区别的: 1,dictionary 允许空键和空值,keys()函数返回的是一个迭代器; 2,abstractmap的keyset返回的是一个 set,dictionary的方法没有abstractmap丰富。

                   其次,hashtable与concurrenthashmap是线程安全的,但是方式上不一样: hashtable 是直接在方法上加 synchronized ; 而concurrenthashmap是在table的node上加synchronized,更加细致,也更有效率。

                   最后,对于 hashmap 中 冲突后 链地址法 的实现(hashtable中用的是 rehash法,对于这一点,从其使用的是 entry<?,?>[] table; 也可以看出),记得在1.7版本看到的是直接加到table中当前节点的前边添加新冲突的node;但是对于1.8的实现,发现不是直接添加,而是使用 红黑树(根据value进行构造) 进行处理