linkedhashmap、treemap、hashmap、ConcurrentSkipListMap、hashtable的区别

一、linkedhashmap与hashmap的主要区别:

  • LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的。
  • HashMap无序;LinkedHashMap有序,可分为插入顺序和访问顺序两种。如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)。
  • LinkedHashMap存取数据,还是跟HashMap一样使用的Entry[]的方式,双向链表只是为了保证顺序。
  • LinkedHashMap是线程不安全的。

二、linkedhashmap简单总结:

1.LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构。该结构由数组和链表+红黑树 在此基础上LinkedHashMap 增加了一条双向链表,保持遍历顺序和插入顺序一致的问题。(双向链表保证遍历和插入顺序一致,有序)  

2. 在实现上,LinkedHashMap 很多方法直接继承自 HashMap(比如put  remove方法就是直接用的父类的),仅为维护双向链表覆写了部分方法(get()方法是重写的)。

3.LinkedHashMap使用的键值对节点是Entity 他继承了hashMap 的Node,并新增了两个引用,分别是 before 和 after。这两个引用的用途不难理解,也就是用于维护双向链表.

4.链表的建立过程是在插入键值对节点时开始的,初始情况下,让 LinkedHashMap 的 head (头)和 tail(尾) 引用同时指向新节点,链表就算建立起来了。随后不断有新节点插入,通过将新节点接在 tail 引用指向节点的后面(尾插),即可实现链表的更新

5.LinkedHashMap 允许使用null值和null键, 线程是不安全的,虽然底层使用了双线链表,但是增删相对快了。因为他底层的Entity 保留了hashMap  node 的next 属性。(增加了双链表,其增删效率变快了,但保证了有序)

6.如何实现迭代有序?

  重新定义了数组中保存的元素Entry(继承于HashMap.node),该Entry除了保存当前对象的引用外,还保存了其上一个元素before和下一个元素after的引用,从而在哈希表的基础上又构成了双向链接列表。仍然保留next属性,所以既可像HashMap一样快速查找,用next获取该链表下一个Entry,也可以通过双向链接,通过after完成所有数据的有序迭代.

7.竟然inkHashMap 的put 方法是直接调用父类hashMap的,但在 HashMap 中,put 方法插入的是 HashMap 内部类 Node 类型的节点,该类型的节点并不具备与 LinkedHashMap 内部类 Entry 及其子类型节点组成链表的能力。那么,LinkedHashMap 是怎样建立链表的呢?

   虽然linkHashMap 调用的是hashMap中的put 方法,但是linkHashMap 重写了,了一部分方法,其中就有  newNode(int hash, K key, V value, Node<K,V> e)、linkNodeLast(LinkedHashMap.Entry<K,V> p)

   这两个方法就是 第一个方法就是新建一个 linkHasnMap 的Entity 方法,而 linkNodeLast 方法就是为了把Entity 接在链表的尾部。

8.链表节点的删除过程

   与插入操作一样,LinkedHashMap 删除操作相关的代码也是直接用父类的实现,但是LinkHashMap 重写了removeNode()方法 afterNodeRemoval()方法,该removeNode方法在hashMap 删除的基础上有调用了afterNodeRemoval 回调方法。完成删除。

删除的过程并不复杂,上面这么多代码其实就做了三件事:

  1. 根据 hash 定位到桶位置
  2. 遍历链表或调用红黑树相关的删除方法
  3. 从 LinkedHashMap 维护的双链表中移除要删除的节点

9、linkedhashmap的排序有两种:

1)插入排序和输出排序一致,即插入的是什么数据,读出来的就是什么数据。(默认的构造方法采用插入顺序)

2)访问顺序,即每次读取一个节点后该节点会被移动到链表尾。(数据库连接池)

(定义linkedhashmap要用你哪种排序方法,有一个参数accessOrder来规定,默认为false即插入顺序,按照put进来的顺序进行排序。true则为访问顺序。一般的情况都是使用默认的插入顺序。)

详细看:https://segmentfault.com/a/1190000012964859

三、treemap和sortmap

1.TreeMap实现了SortedMap接口,保证了有序性。默认的排序是根据key值进行升序排序,也可以重写comparator方法来根据value进行排序具体取决于使用的构造方法。不允许有null值null键。TreeMap是线程不安全的。

2.TreeMap基于红黑树(Red-Black tree)实现TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n)

TreeMap中默认的排序为升序,如果要改变其排序可以自己写一个Comparator,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

四、treemap、hashmap、hashtable、linkedhashmap的主要区别和应用场景

1、Map主要用于存储健值对,根据键得到值,因此不允许键重复(重复了覆盖了),但允许值重复。

2、只有hashtable同步安全,其他都不安全。(hashtable用sychronized修饰但效率偏低)

3、treemap和linkedhashmap是有序的,hashmap和hashtable是无序的。其中linkedhashmap有插入排序和访问排序,一般在要求输出的数据和插入的数据顺序一致的采用linkedhashmap(默认的插入排序,先插入排前面)。而treemap是按key值的大小进行排序的(默认升序可自定义),要求自然排序/自定义排序的可使用treemap。

4、效率:linkedhashmap继承hashmap(很多方法都是用父类的,get重写,put部分方法重写等),也继承了next参数所以其效率和hashmap差不多(linkedhashmap是要对插入的元素进行记录排序的,所以可能效率低一点)(在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。)

而hashmap和treemap:treemap的插入效率低于hashmap(因为需要不断Compare比较,其排序消耗比linkedhashmap高),且treemap的查找性能也是普遍低于hashmap的。(为何treemap的查找低于hashmap?hashmap是基于链表+红黑树,会根据长度改变其结构增加其性能。而treemap一直用红黑树。那其get方法怎么取到有序元素的?)

五、ConcurrentSkipListMap(安全的跳表map)

 TreeMap与ConcurrentSkipListMap相比较

Ø  Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,通过“空间来换取时间”的一个算法,在每个节点中增加了向前的指针,在插入、删除、查找时可以忽略一些不可能涉及到的结点,从而提高了效率。
从概率上保持数据结构的平衡比显示的保持数据结构平衡要简单的多。对于大多数应用,用Skip list要比用树算法相对简单。由于Skip list比较简单,实现起来会比较容易,虽然和平衡树有着相同的时间复杂度(O(logn)),但是skip list的常数项会相对小很多。Skip list在空间上也比较节省。一个节点平均只需要1.333个指针(甚至更少)。

Skip list的性质

(1) 由很多层结构组成,level是通过一定的概率随机产生的。
(2) 每一层都是一个有序的链表,默认是升序,也可以根据创建映射时所提供的Comparator进行排序,具体取决于使用的构造方法。
(3) 最底层(Level 1)的链表包含所有元素。
(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

Ø  ConcurrentSkipListMap具有Skip list的性质 ,并且适用于大规模数据的并发访问。多个线程可以安全地并发执行插入、移除、更新和访问操作。与其他有锁机制的数据结构在巨大的压力下相比有优势。

查找功能在50W数据量以后,TreeMap更有效率,因为ConcurrentSkipListMap自带锁机制,会占用一些效率,但对于多线程并发的环境下,ConcurrentSkipListMap的效率会比Treep要好的。

参考:https://blog.csdn.net/weixin_33796205/article/details/85844520

六、HashTable和HashMap区别

继承不同。

public class Hashtable extends Dictionary implements Map public class HashMap extends AbstractMap implements Map

Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

Hashtable中,keyvalue都不允许出现null值。

HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

两个遍历方式的内部实现上不同。

HashtableHashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

HashtableHashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTablehash数组默认大小是11,增加的方式是 old*2+1HashMaphash数组的默认大小是16,而且一定是2的指数。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值