Java集合归纳-Map

Map概要

上一篇总结了Set集合的一些常用知识点,为何紧接着总结Map呢?

因为Map和Set在底层实现上可以说是一种包装的关系,先看看Map的结构示意图。

这里写图片描述

上图中的两个桶分别代表Map集合里保存的两组值,分别是Key值和Value值,Key和Value都可以是任何引用类型且他们之间保持着一一对应的关系,这一点是Map最基本的。Key值不允许重复,且无需,是不是和Set很像呢,其实把Map里的所有Key值拉出来单独看,就是一个Set集合,没有顺序,不可重复。

而如果我们把Map中所有的Value放在一起,他们就又很类似一个List结构,即元素之间可以重复,每个元素都通过“索引”查找,只不过Map的索引不是整型而是Key值而已。

就像在第一章节Java集合归纳-<一>集合概述中说的那样,Set的实现可以说就是一个所有value值为null的Map结构,Java先实现了Map,再包装一个所有value值为null的Map来实现Set。基于这一点,可以在熟悉Set之后更加方便的牢记Map的特性,反之亦可。就连他们俩之间的子类实现都是同出一辙,HashMap、LinkedHashMap、SortedMap(Interface)、TreeMap。

entrySet和keySet

Map接口中定义的方法都是针对Map中存储对象引用的查询和操作,实际使用过程中根据方法名都能大概推测其功能,这里就不过多赘述,只挑几个比较值得一说的功能来看。

  • Set entrySet():返回Map中存储的Key-Value对所组成的Set集合,每个元素都是Map.Entry,Entry是Map的内部类,可以理解为一个桶(bucket)的入口。
  • Set keySet():返回该Map中存储的所有Key值所组成的集合

有Key的Set,有Key-Value的Set,为什么没有Value的Set,因为Value可重复,从这个设定又可以反应Value存储的特性,加深我们对Map集合特性的记忆。

上面两个方法,经常可以用来对Map集合存储的元素进行迭代遍历,对Map中的对象有一个宏观的把控。

HashMap和Hashtable

区别

  • Hashtable(注意写法)是一个线程安全的Map子类实现,而HashMap不是线程安全的Map子类实现。相对的,HashMap的性能会更好,大部分情况下,不考虑多线程环境下的运行时,我们都应该选择使用HashMap
  • Hashtable不允许使用null作为Key或者Value值,HashMap可以,但要注意的是HashMap的Key值也只允许存在一个为null的对象,毕竟Key值还是要遵循Map的不可重复性。

Hashtable与Vector

为什么把这两个集合放在一起讲,是因为他们的“命运”是相似的,都是古老的Java类,甚至Hashtable的命名规则都没有遵循Java的命名规范,他们都有一些古老版本下的操作方法,有些方法名长而复杂,现在都已经逐渐被Collections工具类的Synchronize修饰符所取代,比如synchronizeMap()等等。

hashCode()和equals()

与Set类似,HashMap和Hashtable也不能保证集合中元素的顺序,因此就需要保证Key值得唯一性。为了Key值得唯一性,就需要一个判断Key值是否相等的标准,这个标准就是:两个Key值通过equals()方法比较返回true,那么两个Key的hashCode()返回的值也应该相等

插入元素判定流程图

这里写图片描述

简单的画了一个插入元素时,HashMap和Hashtable的判定流程图,说一下图中红字条件为NO的两条判定线,这两种插入情况有点区别。

  • Type1:hashCode()返回值不一样,说明两个Key值在hash表中的存储地址不一样,新插入的元素和其他元素一样,散列在hash表的各个bucket(桶)下,此时的存储性能是最优的。
  • Type2:hashCode()返回值一样,Key的值equals()返回false,说明此时新插入的元素和集合中某一元素存储地址相等,他们将会放在同一个bucket(桶)下,以链表维护,如下图所示。

这里写图片描述

所以这也是为什么我们常说,HashMap和Hashtable其实就是一个以数组为主体,链表解决“哈希冲突”的集合

SortedMap接口和TreeMap

和Set的派生设置一样,Map也有一个SortedMap接口和一个它的实现类TreeMap。TreeMap的底层就是由一个红黑树数据结构实现的,每一个键值对都是红黑树的一个节点,所以了解红黑树结构对于理解TreeMap有很重要的意义。关于红黑树的介绍,我推荐大家看看这篇文章红黑树(一)之 原理和算法详细介绍,作者讲得很细致生动,看一遍就能有一个大致的体会。

Comparable接口和compareTo()方法

和HashMap、Hashtable类似,他们判断元素相等的标准有equals()和hashCode(),TreeMap自己的判断标准则是Comparable接口下的compareTo()方法,当两个元素的Key值通过compareTo()毕竟返回0时,说明两个元素的Key值是相等的。因此,TreeMap中存放的元素都要求实现Comparable接口,这点和之前讲过的TreeSet一致。

总结

Map的常用实现类HashMap、Hashtable、TreeMap。

  • HashMap和Hashtable的实现机制几乎一样,区别在于,Hashtable是古老的线程安全集合,性能较HashMap来说更差一些。
  • TreeMap通常比HashMap和Hashtable都要慢,因为它的底层需要树结构去维护元素之间的次序,所以TreeMap中的键值对总是处于排序状态,无须对其内部元素进行排序操作。在实际应用中,我们可以调用TreeMap的keySet()方法获取TreeMap中所有Key排好序的Set集合,通过toArray()方法生成Key数组,并使用Arrays的binarySearch()方法对于已排好序的数组做二分查找,效率很高。
  • 除非我们需要Map中的元素维持有序状态,否则我们都应当优先考虑使用HashMap
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章