一、简介

 
  Map接口下存在实现类HashMap、LinkedHashMap(前者的子类)、EnumMap,并有子接口SortedMap,该子接口下有TreeMap。仔细观察可以发现Map接口下的派生类与Set接口下的派生类十分相似,至少从名字上就不难看出。
  Map对象中存储的对象以键值对的形式存在,其中key不允许重复,value可以重复。key集合可以理解为一个Set集合,即任何两个key使用equals()方法比较的结果都为false。事实上,Map中封装了一个内部类Entry用来封装键值对,而在计算Entry的存储位置时只考虑key。

二、HashMap与Hashtable

 
  这二者的关系类似于ArrayList与Vector的关系。二者的区别如下:

  • HashMap线程不安全,Hashtable线程安全.
  • HashMap中的key和value可以为null,在Hashtable中无论是key还是value都不允许为null。
      判断两个key是否相同的标准是equals()方法返回true,hashCode值也相等。与HashSet类似的是,当我们使用引用变量作为key并在之后修改了key时,那么我们遍无法再访问修改过的key所对应的值。

三、性能选项

 

  对于hash类的集合来说,他们都是通过hash算法来计算元素的存储位置(Map中用来决定key的存储位置),并通过hash算法来控制集合的大小。

  hash表中存储元素的位置称为“桶”,桶的位置由元素hashCode值决定。通常情况下一个桶中存储一个元素,此时hash表的性能也最好。但发生hash冲突时,一个桶中就会存储多个元素,这些元素按照链表的形式存储。如下图所示:

java key可以重复的map_hash表

  

  因为HashSet、HashMap、Hashtable都是用hash算法来决定其元素的存储位置,因此他们的hash表包含以下元素:

  • 容量(capacity):hash表中桶的数量。
  • 初始化容量(initial capacity):创建表时的桶数量,可以再构造函数中设置。
  • 尺寸(size):记录当前表中存储元素的个数。
  • 负载因子(load factor):size/capacity轻负载的hash表有良好的性能,但是过于为了追求轻负载将hash表的容量设置的过大则会导致内存的浪费。
      除此之外hash表中还存在一个负载极限,当负载因子达到负载极限时,hash表会自动扩容,并进行元素的重新分配(rehash)。

四、线程安全

 
  对于Set、List、Map等实现类Java提供了工具类Collections。其中提供了多个synchronizedXxx()方法用来将集合包装成线程安全的集合。