Map

来源:互联网 发布:哪里申请免费域名 编辑:程序博客网 时间:2024/06/16 19:42
Map用于保存具有映射关系的数据,因此Map集合里保存这两组值,一组用于保存Map里的key,另一组值用于保存Map里
的value,key和value都可以是任何引用类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals
方法比较总是返回false。
key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。如果把Map的两组值拆开来看

,Map里的数据如下图所示的结构。


从上图可以看出,如果把Map里的所有key放在一起看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不
能重复),实际上Map确实包含了一个keySet()方法,用于返回Map所有key做成的Set集合。
不仅如此,Map里key集合和Set集合里元素的存储方式也很像,Map子类和Set子类在名字上也惊人的相似:如Set接口下
有HashSet、LinkedHashSet、SortedSet(接口)、TreeSet、EnumSet等实现类和子接口,而Map接口下则有HashMap、
LinkedHashMap、SortedMap(接口)、TreeMap、EnumMap等实现类和子接口。正如它们的名字所暗示的,Map的这些实现
类和子接口中key集存储形式和对应Set集合中元素的存储形式完全相同。
如果把Map的value放在一起看,他们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引来查找
,只是Map中的索引不再使用整数值,而是以另一个对象来作为索引。如果需要从List集合中取出元素,需要提供该元素的
数字索引;如果需要从Map中取出元素,需要提供该元素的key索引。因此,Map有时也被成为字典,或关联数组。

HashMap和Hashtable实现类

HashMap和Hashtable都是Map接口的典型实现类,他们之间的关系完全类似于ArrayList和Vector的关系:Hashtable是
一个古老的Map实现类,它从JDK1.0起就已经出现了,当他出现时,Java还没有提供Map接口,所以他包含了两个繁琐的方法
:elements()(类似于Map接口定义的values()方法)和keys()(类似于Map接口定义的keySet()方法),现在很少使用
这两个方法。
除此之外,Hashtable和HashMap存在两点典型区别:
== Hashtable是一个线程安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable性能高一点;但如果
有多条线程访问同一个Map对象时,使用Hashtable实现类会更好。
== Hashtable不允许使用null作为key和value,如果试图把null值放进Hashtable中,将会引发NullPointException
异常;但HashMap可以使用null作为key或value。
由于HashMap里的key不能重复,所以HashMap里最多只有一项key-value对的key为null,但可以有无数项key-value
对的value为null。下面程序示范了用null值作为HashMap的key或value的情形。

[java] view plaincopy
  1. public class NullInHashMap {  
  2.   
  3.     public static void main(String[] args) {  
  4.         HashMap hm = new HashMap();  
  5.         hm.put(null,null);  
  6.         hm.put(null,null);//这一对key-value插入不进去  
  7.         hm.put("a",null);  
  8.         System.out.println(hm);//{null=null, a=null}  
  9.     }  
  10. }  

根据上面程序的打印结果可以看出,HashMap重写了toString()方法,实际所以Map实现类都重写了toString()方法,
调用Map对象的toString()方法总是返回如下格式的字符串:{key1=value1, key2=value2} 
从Hashtable的类名上就可以看出它是一个古老的类,它的命名甚至没有遵守Java的命名规范:每个单词的首字母都应该
大写。注意:劲量少用Hashtable实现类,即使需要创建线程安全的Map实现类,也可以通过Collections工具类来把HashMap
编程线程安全的,无须使用Hashtable实现类。 
为了成功的在HashMap、Hashtable中存储、获取对象,用作key的对象必须实现hashCode方法和equals方法。
与HashSet集合不能保证元素的顺序一样,HashMap、Hashtable也不能保证其中key-value对的顺序。类似于HashSet的
是,HashMap、Hashtable判断两个key相等的标准也是:两个key通过equals方法比较返回true,两个key的hashCode值也
相等。 
除此之外,HashMap、Hashtable中还包含一个containsValue方法用于判断是否包含指定value。其实HashMap、Hashtable
判断两个value相等的标准更简单:只要两个对象通过equals比较返回true即可。 
注意:当使用自定义类作为HashMap、Hashtable的key时,如果重写该类的equals(Object obj)和hashCode()方法,
应该保证两个方法的判断标准一致:当两个key通过equals方法比较返回true时,两个key的hashCode值也应该相同。因为
HashMap、Hashtable保存key的方式与HashSet保存集合元素的方式完全相同,所以HashMap、Hashtable对key的要求与
HashSet对集合元素的要求完全相同。
与HashSet类似的是,如果使用可变对象作为HashMap、Hashtable的key,并且程序修改了作为key的可变对象,可能
引发与HashSet类似的情形:程序无法准确访问到Map中被修改过key。 所以说尽量不要使用可变对象作为HashMap、Hashtable
的key。

LinkedHashMap可以避免需要对HashMap、Hashtable里的key-value对进行排序(只要插入key-value对时保持顺序即可)。
LinkedHashMap需要维护元素的插入顺序,因此性能略低于HashMap的性能,但在迭代访问Map里的全部元素时将有很好的性能,
因为它以链表来维护内部顺序。 
0 0