Java中各个HashMap子类的介绍以及使用场景

摘要

  • HashMap是日常开发中用到频率相当高的一种键值对处理的数据类型,1.8以后JDK对HashMap的底层进行了优化,引入了红黑树等的数据结构以及扩容的优化,本文着重介绍HashMap的各个子类,以及其使用场景

HashMap简单介绍

  • Java为数据结构中的映射定义了一个接口java.util.Map,分别是HashMap、Hashtable、LinkedHashMap和TreeMap,类继承关系如下图所示:

在这里插入图片描述

  • 图是网上扣得☺
  • JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。
    *​ JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间

各个子类的简单介绍以及使用场景:

  • HashMap:它是根据HashCode值来存储数据,大多数的情况下可以直接定位到它的值,所以访问数据挺快的。HashMap保证的键的唯一不重复,需要重写的ashcode() 和 quals() 方法。 在非并发操作的情况下,HashMap就可以完成正常的需求。需要注意一点,HashMap是非线程安全的,任一时刻可以有多个线程同时重写HashMap,可能会导致数据的不一致,而且多线程的环境下,HashMap进行put操作会引起死循环,故在并发情况下,不能使用hashMap。
  • ConcurrentHashMap:介绍HashMap中说到了它的使用场景中多线程会有线程不安全的问题,既然问题出现,就会有解决的方法。我这边介绍两个方案,一是使用Collections的 synchronizedMap方法使HashMap具有线程安全的能力,二就是使用concurrentHashMap。ConcurrentHashMap 是设计为非阻塞的。在更新时会局部锁住某部分数据,但不会把整个表都锁住。同步读取操作则是完全非阻塞的。好处是在保证合理的同步前提下,效率很高。坏处是严格来说读取操作不能保证反映最近的更新。例如线程A调用putAll写入大量数据,期间线程B调用get,则只能get到目前为止已经顺利插入的部分数据。
    应该根据具体的应用场景选择合适的HashMap。
  • Hashtable:功能与HashMap类似,不通点是,承自Dictionary类,并且是线程安全的,但在任一时间只有一个线程能写Hashtable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。
  • LinkedHashMap:LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。在需要保证顺序的情境下,使用LinkedHashMap。
  • TreeMap:TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

结束

  • 一个人走的快,一群人走的远,一起学习,一起进步。

猜你喜欢

转载自blog.csdn.net/qq_42722951/article/details/107807352
今日推荐