Map子类重要源码分析对比&HashMap&HashTable&TreeMap&IdentityHashMap&WeakHashMap
2017-02-08 14:47
549 查看
Map是Java最常用的中最常用的集合之一。
它的子类有
【HashMap源码分析】(http://blog.csdn.net/chdjj/article/details/38553163)
【HashMap实现原理分析】
http://blog.csdn.net/vking_wang/article/details/14166593
【HashTable源码分析】(http://blog.csdn.net/chdjj/article/details/38581035)
HashTable是jdk1.0产生的,HashMap是jdk1.2产生的。HashMap其实就是在HashTable的细节上做了改动和完善。
HashTable和HashMap的时间复杂度为o(1)。空间复杂度不一定【这个是可以根据构造函数变化的】
主要不同如下
源码分析:
不同点1
不同点2
其中值不能为空非常明显,至于key不能为空,是在这句代码
hash码根据key的地址产生,key为空自然就会有空指针异常
判断了key值,value不用管。
不同点3
HashTable要了这个contains主要是判断value非空的,到了HashMap这里value已经可以为空了。所以就把这个易混淆的方法丢弃了。
【TreeMap的源码分析】(http://blog.csdn.net/chenssy/article/details/26668941)
这个类与HashMap的不同
TreeMap是有序的,因为它的数据结构是红黑树【一种平衡二叉搜索树】。它的时间复杂度是log2(n);
至于源码及分析,见上面的Blog【强烈推荐一波,这个Blog对源码及红黑树的分析非常到位】
【 IdentityHashMap分析】(http://blog.csdn.net/hudashi/article/details/6947625)
这个类与HashMap的主要不同有两点
源码如下:
不同点1
这句代码
这句代码
很明显前者根据地址判断相同,后者根据key的hash码和来内容来判断
不同点2
IdentityHashMap是通过数组来存储的
至于HashMap
【WeakhashMap分析】(http://mikewang.blog.51cto.com/3826268/880775/)
简单理解就是
WeakHashmap中【key, value】中的key,如果除了WeakHashmap自己对之外没有引用了【联系】,那么这个对象就会被gc。
下面是一个简单的代码,代码来自http://www.jb51.net/article/36948.htm
它的子类有
HashTable HashMap TreeMap IdentityHashMap WeakHashMap
HashTable和HashMap的分析对比
参考Blog【单独的对HashMap和HashTable的分析】【HashMap源码分析】(http://blog.csdn.net/chdjj/article/details/38553163)
【HashMap实现原理分析】
http://blog.csdn.net/vking_wang/article/details/14166593
【HashTable源码分析】(http://blog.csdn.net/chdjj/article/details/38581035)
HashTable是jdk1.0产生的,HashMap是jdk1.2产生的。HashMap其实就是在HashTable的细节上做了改动和完善。
HashTable和HashMap的时间复杂度为o(1)。空间复杂度不一定【这个是可以根据构造函数变化的】
主要不同如下
1、HashTable是线程安全的。所以跟HashMap比性能差一点。 2、HashTable键、值都不能为null,HashMap都可以为null 3、HashTable的contains()方法容易让人产生歧义,在HashMap把它删掉了
源码分析:
不同点1
//HashTable public synchronized V put(K key, V value) //HashMap public V put(K key, V value)
不同点2
//HashTable public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }
其中值不能为空非常明显,至于key不能为空,是在这句代码
int hash = key.hashCode();
hash码根据key的地址产生,key为空自然就会有空指针异常
//HashMap public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; } ------------------------------------------------------ private V putForNullKey(V value) { for (Entry<K,V> e = table[0]; e != null; e = e.next) { if (e.key == null) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(0, null, value, 0); return null; }
判断了key值,value不用管。
不同点3
//HashTable public synchronized boolean contains(Object value) { if (value == null) { throw new NullPointerException(); } Entry<?,?> tab[] = table; for (int i = tab.length ; i-- > 0 ;) { for (Entry<?,?> e = tab[i] ; e != null ; e = e.next) { if (e.value.equals(value)) { return true; } } } return false; } public boolean containsValue(Object value) { return contains(value); }
HashTable要了这个contains主要是判断value非空的,到了HashMap这里value已经可以为空了。所以就把这个易混淆的方法丢弃了。
TreeMap
参考Blog【TreeMap的源码分析】(http://blog.csdn.net/chenssy/article/details/26668941)
这个类与HashMap的不同
1、数据结构不同【可以说这导致了基本都不一样】
TreeMap是有序的,因为它的数据结构是红黑树【一种平衡二叉搜索树】。它的时间复杂度是log2(n);
至于源码及分析,见上面的Blog【强烈推荐一波,这个Blog对源码及红黑树的分析非常到位】
IdentityHashMap
参考Blog【 IdentityHashMap分析】(http://blog.csdn.net/hudashi/article/details/6947625)
这个类与HashMap的主要不同有两点
1、判断key值相等的方式不同,这也是IdentityHashMap键可以重复的原因 2、数据结构不同【所以IdentityHashMap快一点】
源码如下:
不同点1
public V put(K key, V value) { final Object k = maskNull(key); retryAfterResize: for (;;) { final Object[] tab = table; final int len = tab.length; int i = hash(k, len); for (Object item; (item = tab[i]) != null; i = nextKeyIndex(i, len)) { if (item == k) { @SuppressWarnings("unchecked") V oldValue = (V) tab[i + 1]; tab[i + 1] = value; return oldValue; } } final int s = size + 1; // Use optimized form of 3 * s. // Next capacity is len, 2 * current capacity. if (s + (s << 1) > len && resize(len)) continue retryAfterResize; modCount++; tab[i] = k; tab[i + 1] = value; size = s; return null; } }
这句代码
if(item == k) !
//HashMap public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
这句代码
if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
很明显前者根据地址判断相同,后者根据key的hash码和来内容来判断
不同点2
//IdentityHashMap transient Object[] table;
//HashMap transient Entry[] table;
IdentityHashMap是通过数组来存储的
tab[i] = k; tab[i + 1] = value;
至于HashMap
通过数组table+链Entry
WeakHashMap
参考Blog【WeakhashMap分析】(http://mikewang.blog.51cto.com/3826268/880775/)
简单理解就是
WeakHashmap中【key, value】中的key,如果除了WeakHashmap自己对之外没有引用了【联系】,那么这个对象就会被gc。
下面是一个简单的代码,代码来自http://www.jb51.net/article/36948.htm
import java.util.*; import java.util.Hashtable; /** * Created by hms on 2017/2/8. */ public class MapAnalyze { public static void main(String[] args) { String a = new String("a"); String b = new String("b"); Map weakmap = new WeakHashMap(); Map map = new HashMap(); map.put(a, "aaa"); map.put(b, "bbb"); weakmap.put(a, "aaa"); weakmap.put(b, "bbb"); map.remove(a); a=null; b=null; System.gc(); Iterator i = map.entrySet().iterator(); while (i.hasNext()) { Map.Entry en = (Map.Entry)i.next(); System.out.println("map:"+en.getKey()+":"+en.getValue()); } Iterator j = weakmap.entrySet().iterator(); while (j.hasNext()) { Map.Entry en = (Map.Entry)j.next(); System.out.println("weakmap:"+en.getKey()+":"+en.getValue()); } } }
/** Output map:b:bbb weakmap:b:bbb */
相关文章推荐
- Java集合框架之Map--IdentityHashMap,WeakHashMap,EnumMap源码分析
- Map总结--HashMap/HashTable/TreeMap/WeakHashMap使用场景分析(转)
- jdk 源码分析(2)java hashtable的结构及hashMap对比
- HashMap,HashTable,synchronizedMap,ConcurrentHashMap,TreeMap,IdentityHashMap的比较分析
- Java类集框架——Map接口(Map.Entry接口 Map常用子类HashMap、Hashtable、TreeMap、WeakHashMap)的使用
- HashMap、HashTable、TreeMap 深入分析及源码解析
- Java集合框架(五)—— Map、HashMap、Hashtable、Properties、SortedMap、TreeMap、WeakHashMap、IdentityHashMap、EnumMap
- Map集合,HashMap,HashTable,ConCurrentHashMap,利用Iterator输出Map集合,自定义Map的key类型,TreeMap子类详解
- Java中的集合Map、HashMap、Hashtable、Properties、SortedMap、TreeMap、WeakHashMap、IdentityHashMap、EnumMap(五)
- Hashmap和hashtable三大区别(从源码角度分析为什么map可以存放一个key为null,多个值为null)的特点
- HashMap、HashTable、TreeMap 深入分析及源码解析
- Java容器类List、ArrayList、Vector及map、HashTable、HashMap、TreeMap、LinkedHashap的区别与用法
- java容器--Map{Hashtable,HashMap,WeakHashMap}
- TreeMap排序 & HashMap分析
- 17、Map接口及其常用子类(Hashtable、HashMap、WeakHashMap)
- JAVA.map 接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap.
- HashMap,HashTable,LinkedMap,TreeMap
- 黑马程序员_学习笔记:10) 集合框架2:Set(HashSet、TreeSet)、Map(Hashtable、HashMap、TreeMap)、Collections、Arrays
- Map.Entry<String,String>,map.entrySet()遍历HashMap,HashTable
- java 容器类使用 Collection,Map,HashMap,hashTable,TreeMap,List,Vector,ArrayList的区别