MAP

http://blog.csdn.net/renfufei/article/details/17287729

本文将为你展示如何使用各种不同的map,包括 HashMap, TreeMap, HashTable 以及 LinkedHashMap.

1. Map 概述
图1

在JavaSE中,对Map的实现主要包括: HashMap, TreeMap, HashTable 和 LinkedHashMap.
如果每个类都用一句话来描述,则表述如下:
  • HashMap 使用哈希表(hash table)实现, 在 keys 和/或 values 之中,都是无序的.
  • TreeMap 基于红黑树(red-black tree)数据结构实现, 按 key 排序.
  • LinkedHashMap 保持者插入顺序.
  • Hashtable 与HashMap实现方式一样,但Hashtable属于同步(synchronized)的.
所以如果代码是线程安全的,那么应该使用HashMap,因为Hashtable的同步是有一定量的运行代价的。而现今对于需要同步的Map,使用  ConcurrentHashMap 也比 Hashtable 有更高的效率。
2. HashMap
如果HashMap中的key使用的是自定义的类对象,那么需要遵守 equals() 与 hashCode() 规范.
  1. class Dog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.     public String toString(){     
  8.         return color + " dog";  
  9.     }  
  10. }  
  11.    
  12. public class TestHashMap {  
  13.     public static void main(String[] args) {  
  14.         HashMap<Dog, Integer> hashMap = new HashMap<Dog, Integer>();  
  15.         Dog d1 = new Dog("red");  
  16.         Dog d2 = new Dog("black");  
  17.         Dog d3 = new Dog("white");  
  18.         Dog d4 = new Dog("white");  
  19.    
  20.         hashMap.put(d1, 10);  
  21.         hashMap.put(d2, 15);  
  22.         hashMap.put(d3, 5);  
  23.         hashMap.put(d4, 20);  
  24.    
  25.         //print size  
  26.         System.out.println(hashMap.size());  
  27.    
  28.         //loop HashMap  
  29.         for (Entry<Dog, Integer> entry : hashMap.entrySet()) {  
  30.             System.out.println(entry.getKey().toString() + " - " + entry.getValue());  
  31.         }  
  32.     }  
  33. }  
输出为:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 4  
  2. white dog – 5  
  3. black dog – 15  
  4. red dog – 10  
  5. white dog – 20  
注意看,我们错误地添加了两次"white dogs",但是HashMap 接受了,这严格来说是没意义的,因为现在对"white dogs"的数量产生了混淆.
修正后的 Dog 类如下所示:
  1. class Dog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.    
  8.     public boolean equals(Object o) {  
  9.         return ((Dog) o).color == this.color;  
  10.     }  
  11.    
  12.     public int hashCode() {  
  13.         return color.length();  
  14.     }  
  15.    
  16.     public String toString(){      
  17.         return color + " dog";  
  18.     }  
  19. }  
再运行新的代码,结果如下所示:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. 3  
  2. red dog – 10  
  3. white dog – 20  
  4. black dog – 15  
原因在于 HashMap 不运行两个相同的元素作为KEY.
如果没有重写,使用的就会是 Object 类实现的 hashCode() 和 equals() 方法
默认的 hashCode() 方法实现对每个不同的对象返回不同的整数.
默认的 equals() 方法只比较两个引用是否指向同一个实际对象.
如果你还有疑惑,请阅读:   equals()与hashCode()方法协作约定
3. TreeMap
TreeMap是根据key排序的.我们先看下面的示例来加深 "按key排序" 的印象.
  1. class Dog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.     public boolean equals(Object o) {  
  8.         return ((Dog) o).color == this.color;  
  9.     }  
  10.    
  11.     public int hashCode() {  
  12.         return color.length();  
  13.     }  
  14.     public String toString(){     
  15.         return color + " dog";  
  16.     }  
  17. }  
  18.    
  19. public class TestTreeMap {  
  20.     public static void main(String[] args) {  
  21.         Dog d1 = new Dog("red");  
  22.         Dog d2 = new Dog("black");  
  23.         Dog d3 = new Dog("white");  
  24.         Dog d4 = new Dog("white");  
  25.    
  26.         TreeMap<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();  
  27.         treeMap.put(d1, 10);  
  28.         treeMap.put(d2, 15);  
  29.         treeMap.put(d3, 5);  
  30.         treeMap.put(d4, 20);  
  31.    
  32.         for (Entry<Dog, Integer> entry : treeMap.entrySet()) {  
  33.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  34.         }  
  35.     }  
  36. }  
执行后结果如下:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Exception in thread “main” java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable  
  2. at java.util.TreeMap.put(Unknown Source)  
  3. at collection.TestHashMap.main(TestHashMap.java:35)  
既然 TreeMap 是按key排序的,那么key对象就必须可以和另一个对象作比较,因此必须实现 Comparable 接口。
当然,你也可以使用 String 对象作为key,因为 String 类已经实现了 Comparable 接口。
下面,我们修改 Dog 类的代码,使其实现Comparable:
  1. class Dog implements Comparable<Dog>{  
  2.     String color;  
  3.     int size;  
  4.    
  5.     Dog(String c, int s) {  
  6.         color = c;  
  7.         size = s;  
  8.     }  
  9.    
  10.     public String toString(){     
  11.         return color + " dog";  
  12.     }  
  13.    
  14.     @Override  
  15.     public int compareTo(Dog o) {  
  16.         return  o.size - this.size;  
  17.     }  
  18. }  
  19.    
  20. public class TestTreeMap {  
  21.     public static void main(String[] args) {  
  22.         Dog d1 = new Dog("red"30);  
  23.         Dog d2 = new Dog("black"20);  
  24.         Dog d3 = new Dog("white"10);  
  25.         Dog d4 = new Dog("white"10);  
  26.    
  27.         TreeMap<Dog, Integer> treeMap = new TreeMap<Dog, Integer>();  
  28.         treeMap.put(d1, 10);  
  29.         treeMap.put(d2, 15);  
  30.         treeMap.put(d3, 5);  
  31.         treeMap.put(d4, 20);  
  32.    
  33.         for (Entry<Dog, Integer> entry : treeMap.entrySet()) {  
  34.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  35.         }  
  36.     }  
  37. }  
执行后输出的结果是:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. red dog – 10  
  2. black dog – 15  
  3. white dog – 20  
这就是根据key对象排序的结果,此处我们使用了 size(尺寸)来比较 dog.
如果我们把
" Dog d4 = new Dog("white", 10);"
这一行代码替换为
" Dog d4 = new Dog("white", 40);"
那么,执行后的结果为:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. white dog – 20  
  2. red dog – 10  
  3. black dog – 15  
  4. white dog – 5  
原因是 TreeMap 使用 compareTo() 方法来比较 key对象,不同的 size 就被认为是不同的 dog.
4. Hashtable
根据Java文档, HashMap 类基本上等同于 Hashtable, 区别仅仅在于: HashMap 不是同步的,并且运行 null 值.
5. LinkedHashMap
LinkedHashMap 是 HashMap 的子类. 所以继承了所有 HashMap 的特性,另外, 链表保持了插入的顺序.
我们复制上面的 HashMap 的示例代码,并将HashMap替换为LinkedHashMap:
  1. class Dog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.    
  8.     public boolean equals(Object o) {  
  9.         return ((Dog) o).color == this.color;  
  10.     }  
  11.    
  12.     public int hashCode() {  
  13.         return color.length();  
  14.     }  
  15.    
  16.     public String toString(){     
  17.         return color + " dog";  
  18.     }  
  19. }  
  20.    
  21. public class TestHashMap {  
  22.     public static void main(String[] args) {  
  23.    
  24.         Dog d1 = new Dog("red");  
  25.         Dog d2 = new Dog("black");  
  26.         Dog d3 = new Dog("white");  
  27.         Dog d4 = new Dog("white");  
  28.    
  29.         LinkedHashMap<Dog, Integer> linkedHashMap = new LinkedHashMap<Dog, Integer>();  
  30.         linkedHashMap.put(d1, 10);  
  31.         linkedHashMap.put(d2, 15);  
  32.         linkedHashMap.put(d3, 5);  
  33.         linkedHashMap.put(d4, 20);  
  34.    
  35.         for (Entry<Dog, Integer> entry : linkedHashMap.entrySet()) {  
  36.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  37.         }         
  38.     }  
  39. }  
输出结果如下:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. red dog – 10  
  2. black dog – 15  
  3. white dog – 20  
区别在于 HashMap输出的结果顺序与插入顺序是无关的. 
下面再次列出使用 HashMap的输出结果以供对比:
[plain] view plain copy 在CODE上查看代码片 派生到我的代码片
  1. red dog – 10  
  2. white dog – 20  
  3. black dog – 15 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值