一 HashMap类和Hashtable类的介绍
1 HashMap类和Hashtable类概述
HashMap和Hashtable都是Map接口的典型实现类,他们之间的关系完全类似于ArrayList和Vector的关系。
2 HashMap类和Hashtable类的区别
- Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能高一点;但如果有多线程访问同一个Map对象时,使用Hashtable实现类会更好。
- Hashtable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointerException异常;但HashMap可以使用null作为key或value。
3 代码示例
import java.util.*; public class NullInHashMap { public static void main(String[] args) { HashMap hm = new HashMap(); // 试图将两个key为null的key-value对放入HashMap中 hm.put(null , null); hm.put(null , null); // ① // 将一个value为null的key-value对放入HashMap中 hm.put("a" , null); // ② // 输出Map对象 System.out.println(hm); } }
4 运行结果
{null=null, a=null}
5 结果分析
由于HashMap里的key不能重复,所以HashMap里最多只有一个key-value对的key为null,但可以由无数多个key-value对的value为null,该程序演示了用null值作为HashMap的key和value的情形。
二 Hashtable类的典型应用
1 代码示例
import java.util.*; class A { int count; public A(int count) { this.count = count; } // 根据count的值来判断两个对象是否相等。 public boolean equals(Object obj) { if (obj == this) return true; if (obj != null && obj.getClass() == A.class) { A a = (A)obj; return this.count == a.count; } return false; } // 根据count来计算hashCode值。 public int hashCode() { return this.count; } } class B { // 重写equals()方法,B对象与任何对象通过equals()方法比较都返回true public boolean equals(Object obj) { return true; } } public class HashtableTest { public static void main(String[] args) { Hashtable ht = new Hashtable(); ht.put(new A(60000) , "爸爸"); ht.put(new A(87563) , "妈妈"); ht.put(new A(1232) , new B()); System.out.println(ht); // 只要两个对象通过equals比较返回true, // Hashtable就认为它们是相等的value。 // 由于Hashtable中有一个B对象, // 它与任何对象通过equals比较都相等,所以下面输出true。 System.out.println(ht.containsValue("测试字符串")); // ① 输出true // 只要两个A对象的count相等,它们通过equals比较返回true,且hashCode相等 // Hashtable即认为它们是相同的key,所以下面输出true。 System.out.println(ht.containsKey(new A(87563))); // ② 输出true // 下面语句可以删除最后一个key-value对 ht.remove(new A(1232)); //③ System.out.println(ht); } }
2 运行结果
{A@ea60=爸爸, A@1560b=妈妈, A@4d0=B@1db9742}
true
true
3 结果分析
当使用自定义类作为Hashtable的key时,如果重写该类的equals和hashCode方法,则应该保证这两个方法的判断标准一致,当两个Key通过equals方法比较返回true时,两个key的hashCode返回值也应该相同。
三 HashMap类的典型应用
1 代码示例
import java.util.*; public class HashMapErrorTest { public static void main(String[] args) { HashMap ht = new HashMap(); // 此处的A类与前一个程序的A类是同一个类 ht.put(new A(60000) , "孙悟空"); ht.put(new A(87563) , "八戒"); // 获得Hashtable的key Set集合对应的Iterator迭代器 Iterator it = ht.keySet().iterator(); // 取出Map中第一个key,并修改它的count值 A first = (A)it.next(); first.count = 87563; // ① // 输出{A@1560b=孙悟空, A@1560b=八戒} System.out.println(ht); // 只能删除没有被修改过的key所对应的key-value对 ht.remove(new A(87563)); System.out.println(ht); // 无法获取剩下的value,下面两行代码都将输出null。 System.out.println(ht.get(new A(87563))); // ② 输出null System.out.println(ht.get(new A(60000))); // ③ 输出null } }
2 运行结果
{A@1560b=孙悟空, A@1560b=八戒}
{A@1560b=孙悟空}
null
null
3 结果分析
与HashSet类似,尽量不要使用可变变量作为HashMap的key。如果确实需要使用可变变量作为HashMap的key,则尽量不要在程序中修改作为key的可变变量。