hashmap, treemap, hashtable, hashcode 的使用和探讨
来源:互联网 发布:马伯庸 三国 知乎 编辑:程序博客网 时间:2024/06/05 10:25
1. 基本使用
a. 在HashMap中通过get()来获取value,通过put()来插入value,ContainsKey()则用来检验对象是否已经存在。可以看出,和ArrayList的操作相比,HashMap除了通过key索引其内容之外,别的方面差异并不大;
b. 可以使用values()方法返回一个Collection物件,如果您需要一次选代Map中所有的物件;
c. HashMap通过hashcode对其内容进行快速查找,而TreeMap中所有的元素都保持着某种固定的顺序;
d. HashMap使用Hash Table,因而它有自己的排序方式,如果您想要在选代所有的物件时,依照插入的顺序来排序,则可以使用LinkedHashMap,它是HashMap 的子类。
System.out.println("Sequence..."); Map hashmap = new HashMap(); hashmap.put("a", "aa"); hashmap.put("b", "bb"); hashmap.put("c", "cc"); hashmap.put("d", "dd"); Iterator iterator_hashmap = hashmap.keySet().iterator(); while (iterator_hashmap.hasNext()) { Object key = iterator_hashmap.next(); System.out.println("HashMap:" + hashmap.get(key)); } Map linkedhashmap = new LinkedHashMap(); linkedhashmap.put("a", "aa"); linkedhashmap.put("b", "bb"); linkedhashmap.put("c", "cc"); linkedhashmap.put("d", "dd"); Collection collection = linkedhashmap.values(); Iterator iterator_linkedhashmap = collection.iterator(); while (iterator_linkedhashmap.hasNext()) { System.out.println("LinkedHashMap:" + iterator_linkedhashmap.next()); } Hashtable hashtable = new Hashtable(); hashtable.put("a", "aa"); hashtable.put("b", "bb"); hashtable.put("c", "cc"); hashtable.put("d", "dd"); Iterator iterator_hashtable = hashtable.keySet().iterator(); while (iterator_hashtable.hasNext()) { Object key = iterator_hashtable.next(); System.out.println("HashTable:" + hashtable.get(key)); } Map treemap = new TreeMap(); treemap.put("a", "aa"); treemap.put("b", "bb"); treemap.put("c", "cc"); treemap.put("d", "dd"); Iterator iterator_treemap = treemap.keySet().iterator(); while (iterator_treemap.hasNext()) { Object key = iterator_treemap.next(); System.out.println("TreeMap:" + treemap.get(key)); }
2. keySet 和 entrySet 的比较
对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。而entryset只是遍历了第一次,它把key和value都放到了entry中,所以就快了。 HashMap使用很多,比如导入信息时就要用到,因大部分导入的信息要去判断是否有重复的信息,这样就可以利用containsKey来进行处理了,而不用在插入的时候去进行处理。
System.out.println("efficiency of keySet and entrySet..."); HashMap k_hashmap = new HashMap(); for (int i = 0; i < 1000; i++) { k_hashmap.put("" + i, "hello"); } long k_bs = Calendar.getInstance().getTimeInMillis(); Iterator iterator = k_hashmap.keySet().iterator(); while (iterator.hasNext()) { System.out.println(k_hashmap.get(iterator.next())); } System.out.println(Calendar.getInstance().getTimeInMillis() - k_bs); HashMap e_hashmap = new java.util.HashMap(); for (int i = 0; i < 1000; i++) { e_hashmap.put("" + i, "hello"); } long e_bs = Calendar.getInstance().getTimeInMillis(); java.util.Iterator it = e_hashmap.entrySet().iterator(); while (it.hasNext()) { java.util.Map.Entry entry = (java.util.Map.Entry) it.next(); System.out.println(entry.getValue()); } System.out.println(Calendar.getInstance().getTimeInMillis() - e_bs);
3. HashCode在其中的探讨
下面的程序无论运行多少次,得到的结果都是"Not found"。也就是说索引KeyElement(5)并不在HashMap中.
KeyElement的HashCode方法继承自Object,而Object中的HashCode方法返回的HashCode对应于当前的地址,也就是说对于不同的对象,即使它们的内容完全相同,用HashCode()返回的值也会不同。这样实际上违背了我们的意图。因为我们在使用HashMap时,希望利用相同内容的对象索引得到相同的目标对象,这就需要HashCode()在此时能够返回相同的值。在下面的例子中,我们期望new KeyElement(i) (i=5)与 KeyElement test=new KeyElement(5)是相同的,而实际上这是两个不同的对象,尽管它们的内容相同,但它们在内存中的地址不同。因此很自然的,下面的程序得不到我们设想的结果。
public class KeyElement { int number; public KeyElement(int n) { number = n; }} HashMap hm = new HashMap(); for(int i=0; i<10; i++) hm.put(new KeyElement(i), "aa"+1); KeyElement testKey = new KeyElement(5); if (hm.containsKey(testKey)) { System.out.println(hm.get(testKey)); } else { System.out.println("Not found"); }
如果我们把KeyElement类重新修改一下,就可以得到我们要的结果了。在这里KeyElement覆盖了Object中的hashCode()和equals()方法。覆盖hashCode()使其以number的值作为hashcode返回,这样对于相同内容的对象来说它们的hashcode也就相同了。而覆盖equals()是为了在HashMap判断两个key是否相等时使结果有意义
public class KeyElement { int number; public KeyElement(int n) { number = n; } public int hashCode() { return number; } public boolean equals(Object o) { return (o instanceof KeyElement) && (number == ((KeyElement) o).number); }}
延伸:
重写HashCode()的原则:
- 不必对每个不同的对象都产生一个唯一的hashcode,只要你的HashCode方法使get()能够得到put()放进去的内容就可以了。即"不为一原则"。
- 生成hashcode的算法尽量使hashcode的值分散一些,不要很多hashcode都集中在一个范围内,这样有利于提高HashMap的性能。即"分散原则"。
掌握了这两条原则,你就能够用好HashMap编写自己的程序了。不知道大家注意没有,java.lang.Object中提供的三个方法:clone(),equals()和hashCode()虽然很典型,但在很多情况下都不能够适用,它们只是简单的由对象的地址得出结果。这就需要我们在自己的程序中重写它们,其实java类库中也重写了千千万万个这样的方法。利用面向对象的多态性——覆盖,Java的设计者很优雅的构建了Java的结构,也更加体现了Java是一门纯OOP语言的特性。
4. HashMap与HashTable的区别
a.HashTable的方法是同步的,HashMap未经同步,所以在多线程场合要手动同步HashMap这个区别就像Vector和ArrayList一样。
b.HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。
c.HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样。
d.HashTable使用Enumeration,HashMap使用Iterator。
以上只是表面的不同,它们的实现也有很大的不同。
e.HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
f.哈希值的使用不同,HashTable直接使用对象的hashCode,代码是这样的:
int hash = key.hashCode();int index = (hash & 0x7FFFFFFF) % tab.length;
int hash = hash(k);int i = indexFor(hash, table.length);static int hash(Object x) { int h = x.hashCode(); h += ~(h << 9); h ^= (h >>> 14); h += (h << 4); h ^= (h >>> 10); return h;}static int indexFor(int h, int length) { return h & (length-1);}
HashMap对null的操作
- hashmap, treemap, hashtable, hashcode 的使用和探讨
- HashMap Hashtable LinkedHashMap 和TreeMap的比较使用
- HashTable,HashMap和TreeMap
- LinkedHashMap、HashMap、Hashtable、TreeMap的比较使用
- hashMap、hashtable和treeMap的区别
- Hashtable、HashMap和TreeMap的区别
- Hashtable、HashMap和TreeMap的区别
- HashMap、HashTable、LinkedHashMap和TreeMap的区别
- HashMap、Hashtable、LinkedHashMap 和TreeMap的区别
- HashMap和Hashtable以及TreeMap的区别
- HashMap和Hashtable,TreeMap的区别
- Hashtable、HashMap和TreeMap的区…
- HashCode和hashMap hashTable
- HashCode和hashMap hashTable
- HashCode和hashMap hashTable
- HashMap Hashtable LinkedHashMap 和TreeMap
- HashMap Hashtable LinkedHashMap 和TreeMap
- HashMap Hashtable LinkedHashMap 和TreeMap
- Android权限列表permission说明
- 国际化程序
- oepncv CvWaitKey
- arm体系结构与汇编100问
- 目前游戏行业内部主要几款游戏引擎的技术对比
- hashmap, treemap, hashtable, hashcode 的使用和探讨
- Android手机壁纸(Android学习随笔二)
- POJ 1258 最小生成树
- python 单引号 正则表示
- Android中手机震动的设置(Vibrator)的步骤(Android学习随笔三)
- poj 2485
- POJ 2255: Tree Recovery
- 幸福不是......
- _CrtSetReportMode 2019