一 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
{A@ea60=爸爸, A@1560b=妈妈}
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的可变变量。