HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap




Map是最重要的数据结构。这篇文章中,我会带你们看看HashMap, TreeMap, HashTable和LinkedHashMap的区别。

1. Map概览

Java SE中有四种常见的Map实现——HashMap, TreeMap, Hashtable和LinkedHashMap。如果我们使用一句话来分别概括它们的特点,就是:

HashMap就是一张hash表,键和值都没有排序。
TreeMap以红-黑树结构为基础,键值按顺序排列。
LinkedHashMap保存了插入时的顺序。
Hashtable是同步的(而HashMap是不同步的)。所以如果在线程安全的环境下应该多使用HashMap,而不是Hashtable,因为Hashtable对同步有额外的开销。
HashMap

如果HashMap的键(key)是自定义的对象,那么需要按规则定义它的equals()和hashCode()方法

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. classDog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.     publicString toString(){     
  8.         returncolor + " dog";  
  9.     }  
  10. }  
  11.    
  12. publicclass TestHashMap {  
  13.     publicstatic void main(String[] args) {  
  14.         HashMap hashMap = newHashMap();  
  15.         Dog d1 = newDog("red");  
  16.         Dog d2 = newDog("black");  
  17.         Dog d3 = newDog("white");  
  18.         Dog d4 = newDog("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 entry : hashMap.entrySet()) {  
  30.             System.out.println(entry.getKey().toString() + " - " + entry.getValue());  
  31.         }  
  32.     }  
  33. }  

输出:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 4  
  2. white dog - 5  
  3. black dog - 15  
  4. red dog - 10  
  5. white dog - 20  

注意,我们错误的将”white dogs”添加了两次,但是HashMap却接受了两只”white dogs”。这不合理(因为HashMap的键不应该重复),我们会搞不清楚真正有多少白色的狗存在。

Dog类应该定义如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. classDog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.    
  8.     publicboolean equals(Object o) {  
  9.         return((Dog) o).color == this.color;  
  10.     }  
  11.    
  12.     publicint hashCode() {  
  13.         returncolor.length();  
  14.     }  
  15.    
  16.     publicString toString(){     
  17.         returncolor + " dog";  
  18.     }  
  19. }  

现在输出结果如下:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. 3  
  2. red dog - 10  
  3. white dog - 20  
  4. black dog - 15  

输出结果如上是因为HashMap不允许有两个相等的元素存在。默认情况下(也就是类没有实现hashCode()和equals()方法时),会使用Object类中的这两个方法。Object类中的hashCode()对于不同的对象会返回不同的整数,而只有两个引用指向的同样的对象时equals()才会返回true。如果你不是很了解hashCode()和equals()的规则,可以看看这篇文章

来看看HashMap最常用的方法,如迭代、打印等。

3. TreeMap

TreeMap的键按顺序排列。让我们先看个例子看看什么叫作“键按顺序排列”。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. classDog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.     publicboolean equals(Object o) {  
  8.         return((Dog) o).color == this.color;  
  9.     }  
  10.    
  11.     publicint hashCode() {  
  12.         returncolor.length();  
  13.     }  
  14.     publicString toString(){     
  15.         returncolor + " dog";  
  16.     }  
  17. }  
  18.    
  19. publicclass TestTreeMap {  
  20.     publicstatic void main(String[] args) {  
  21.         Dog d1 = newDog("red");  
  22.         Dog d2 = newDog("black");  
  23.         Dog d3 = newDog("white");  
  24.         Dog d4 = newDog("white");  
  25.    
  26.         TreeMap treeMap = newTreeMap();  
  27.         treeMap.put(d1,10);  
  28.         treeMap.put(d2,15);  
  29.         treeMap.put(d3,5);  
  30.         treeMap.put(d4,20);  
  31.    
  32.         for(Entry entry : treeMap.entrySet()) {  
  33.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  34.         }  
  35.     }  
  36. }  

输出:

[java]  view plain  copy
 print ? 在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按照键的顺序进行排列对象,所以键的对象之间需要能够比较,所以就要实现Comparable接口。你可以使用String作为键,String已经实现了Comparable接口。

我们来修改下Dog类,让它实现Comparable接口。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. classDog implementsComparable<Dog>{  
  2.     String color;  
  3.     intsize;  
  4.    
  5.     Dog(String c, ints) {  
  6.         color = c;  
  7.         size = s;  
  8.     }  
  9.    
  10.     publicString toString(){     
  11.         returncolor + " dog";  
  12.     }  
  13.    
  14.     @Override  
  15.     publicint compareTo(Dog o) {  
  16.         return o.size - this.size;  
  17.     }  
  18. }  
  19.    
  20. publicclass TestTreeMap {  
  21.     publicstatic void main(String[] args) {  
  22.         Dog d1 = newDog("red",30);  
  23.         Dog d2 = newDog("black",20);  
  24.         Dog d3 = newDog("white",10);  
  25.         Dog d4 = newDog("white",10);  
  26.    
  27.         TreeMap treeMap = newTreeMap();  
  28.         treeMap.put(d1,10);  
  29.         treeMap.put(d2,15);  
  30.         treeMap.put(d3,5);  
  31.         treeMap.put(d4,20);  
  32.    
  33.         for(Entry entry : treeMap.entrySet()) {  
  34.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  35.         }  
  36.     }  
  37. }  

输出:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. red dog - 10  
  2. black dog - 15  
  3. white dog - 20  

结果根据键的排列顺序进行输出,在我们的例子中根据size排序的。

如果我们将“Dog d4 = new Dog(“white”, 10);”替换成“Dog d4 = new Dog(“white”, 40);”,那么输出会变成:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. white dog - 20  
  2. red dog - 10  
  3. black dog - 15  
  4. white dog - 5  

这是因为TreeMap使用compareTo()方法来比较键值的大小,size不相等的狗是不同的狗。

4. Hashtable

Java文档写道:

HashMap类和Hashtable类几乎相同,不同之处在于HashMap是不同步的,也允许接受null键和null值。

5. LinkedHashMap

LinkedHashMap is a subclass of HashMap. That means it inherits the features of HashMap. In addition, the linked list preserves the insertion-order.

Let’s replace the HashMap with LinkedHashMap using the same code used for HashMap.

LinkedHashMap是HashMap的子类,所以LinkedHashMap继承了HashMap的一些属性,它在HashMap基础上增加的特性就是保存了插入对象的顺序。

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. classDog {  
  2.     String color;  
  3.    
  4.     Dog(String c) {  
  5.         color = c;  
  6.     }  
  7.    
  8.     publicboolean equals(Object o) {  
  9.         return((Dog) o).color == this.color;  
  10.     }  
  11.    
  12.     publicint hashCode() {  
  13.         returncolor.length();  
  14.     }  
  15.    
  16.     publicString toString(){     
  17.         returncolor + " dog";  
  18.     }  
  19. }  
  20.    
  21. publicclass TestHashMap {  
  22.     publicstatic void main(String[] args) {  
  23.    
  24.         Dog d1 = newDog("red");  
  25.         Dog d2 = newDog("black");  
  26.         Dog d3 = newDog("white");  
  27.         Dog d4 = newDog("white");  
  28.    
  29.         LinkedHashMap linkedHashMap = newLinkedHashMap();  
  30.         linkedHashMap.put(d1,10);  
  31.         linkedHashMap.put(d2,15);  
  32.         linkedHashMap.put(d3,5);  
  33.         linkedHashMap.put(d4,20);  
  34.    
  35.         for(Entry entry : linkedHashMap.entrySet()) {  
  36.             System.out.println(entry.getKey() + " - " + entry.getValue());  
  37.         }        
  38.     }  
  39. }  

输出:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. red dog - 10  
  2. black dog - 15  
  3. white dog - 20  

如果我们使用HashMap的话,输出将会如下,会打乱插入的顺序:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. red dog - 10  
  2. white dog - 20  
  3. black dog - 15  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值