Java最高

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>查看课程

1.概述

在本文中,我们将探讨内部实施linkedhashmap.班级。linkedhashmap.常见的实现是什么地图界面。

这种特殊实施是一个子类Hashmap.因此共享的核心构建块Hashmap.执行。因此,强烈建议在继续阅读本文之前先复习一下。

2.linkedhashmap.vs.Hashmap.

linkedhashmap.班级非常相似Hashmap.在大多数方面。然而,链接哈希映射是基于哈希表和链表的,以增强哈希映射的功能。

除了默认默认大小16的底层数组之外,它将维护通过其所有条目运行的双链路列表。

为维护元素的顺序,链接的散列表将修改地图。条目类的Hashmap.通过将指针添加到下一个和上一个条目:

静态类条目扩展hashmap.node  {条目之前,之后;条目(int hash,k键,v值,节点 next){super(哈希,键,值,下一个);}}

请注意,条目班级只是添加了两个指针;这使它能够将自己与链表挂钩。除此之外,它使用条目类实现了一个HashMap。

最后,请记住,此链接列表定义迭代的顺序,默认情况下是插入元素(插入顺序)的顺序。

3.插入顺序linkedhashmap.

让我们来看一个链接散列映射实例,它根据条目插入映射的方式对其进行排序。它还保证在映射的整个生命周期中保持这个顺序:

@test public void给gendlinkedhashmap_whengetsorderedkeyset_thencorrect(){linkedhashmap <整数,string> map = new linkedhashmap <>();map.put(1,null);map.cput(2,null);map.put(3,null);map.put(4,null);map.put(5,null);Set keys = map.keySet();Integer [] arr = keys.toArray(新整数[0]);for(int i = 0; i 

在这里,我们只是对链接散列映射中的条目排序进行一个基本的、非决定性的测试。

我们可以保证此测试将始终通过插入顺序作为始终保持。我们对HashMap的保证无法做出同样的保证。

这个属性在接收任何映射、复制并将其返回给调用代码的API中具有很大的优势。如果客户端需要在调用API之前以同样的方式对返回的映射进行排序,那么可以使用链接的散列表。

如果将键重新插入到映射中,则不影响插入顺序。

4.若不想linkedhashmap.

linkedhashmap.提供了一个特殊的构造函数,使我们能够在自定义负载因子(LF)和初始容量之间指定,一种不同的排序机制/策略称为访问顺序:

 map = new LinkedHashMap<>(16, .75f, true);

第一个参数是初始容量,其次是负载因子和最后一个param是订购模式。所以,通过传入真的,我们打开了access-order,而默认是insert -order。

此机制可确保元素的迭代顺序是最后访问元素的顺序,最近访问的最近访问了。

因此,使用这种映射构建一个最近最少使用(LRU)缓存是非常容易和实用的。一个成功的或者得到操作导致进入的访问:

@test public void给gendlinkedhashmap_whenaccessordorworks_thencorrect(){linkedhashmap <整数,字符串>地图= new linkedhashmap <>(16,.75f,true);map.put(1,null);map.cput(2,null);map.put(3,null);map.put(4,null);map.put(5,null);Set keys = map.keySet();assertequal(“[1、2、3、4、5)”,keys.toString ());Map.get(4);assertequals(“[1,2,3,5,4]”,keys.tostring()); map.get(1); assertEquals("[2, 3, 5, 4, 1]", keys.toString()); map.get(3); assertEquals("[2, 5, 4, 1, 3]", keys.toString()); }

注意当我们在地图上执行访问操作时,键集中的元素的顺序将变换。

简单地说,映射上的任何访问操作的结果顺序是,如果要立即执行迭代,则被访问的元素将最后出现。

在上述例子之后,应该显而易见put操作为指定地图中的每个映射生成一个条目访问权限。

自然地,对一个映射视图进行迭代并不影响后备映射的迭代顺序;在地图上只有显式访问操作将影响订单

linkedhashmap.还提供了一种用于维护固定数量的映射的机制,并在需要添加新的情况下继续丢弃最旧的条目。

删除比赛可以覆盖方法以强制自动删除陈旧映射的策略。

在实践中看到这一点,让我们创建自己的链接哈希地图类,以便通过扩展来执行陈旧映射的唯一目的linkedhashmap.:

public class MyLinkedHashMap extends LinkedHashMap {private static final int MAX_ENTRIES = 5;public MyLinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {super(initialCapacity, loadFactor, accessOrder);} @Override protected boolean removeEldestEntry(Map。return size() > MAX_ENTRIES;}}

我们上面的覆盖将允许地图增长到5个条目的最大大小。当大小超过该时,将以丢失地图中的最终端条目的成本插入每个新条目。当前访问时间之前的条目之前所有其他条目的条目:

@Test public void givenlinkedhashmap_whenremoveseldestentry_threct () {LinkedHashMap map = new MyLinkedHashMap<>(16, .75f, true);map.put(1,null);map.cput(2,null);map.put(3,null);map.put(4,null);map.put(5,null);Set keys = map.keySet();assertequal(“[1、2、3、4、5)”,keys.toString ());地图。把(6, null); assertEquals("[2, 3, 4, 5, 6]", keys.toString()); map.put(7, null); assertEquals("[3, 4, 5, 6, 7]", keys.toString()); map.put(8, null); assertEquals("[4, 5, 6, 7, 8]", keys.toString()); }

请注意,当我们向映射中添加新条目时,键集开始处最老的条目不断减少。

5.性能考虑

就像Hashmap.,linkedhashmap.执行基本地图添加、删除和包含操作在常量时间内进行,只要哈希函数的维数良好。它还接受空键和空值。

然而,这常量时间的性能linkedhashmap.可能比恒定时间更糟糕Hashmap.由于维护双链接列表的额外开销。

的集合视图的迭代linkedhashmap.也需要线性时间上)类似于Hashmap.。另一方面,linkedhashmap.迭代过程中的线性时间性能优于Hashmap.的线性时间

这是因为,因为linkedhashmap.,n上)仅是映射中的条目数,而与容量无关。然而,对于Hashmap.,n容量和大小总结,O(尺寸+容量)。

负载因子和初始容量是精确定义的Hashmap.。但是,请注意选择一个过高的初始容量值的惩罚是不那么严重的linkedhashmap.Hashmap.,随着该类的迭代时间不受容量影响。

6.并发

就像Hashmap.,linkedhashmap.实现不同步。因此,如果您要从多个线程访问它,并且至少有一个线程可能会在结构上更改它,那么它必须是外部同步的。

最好在创建时这样做:

地图m = collections.synchronizedmap(new linkedhashmap());

差异Hashmap.在于需要结构修改的东西。在访问顺序链接散列映射中,仅调用得到API导致结构修改。除此之外,还有去掉

7.结论

在本文中,我们探索了Javalinkedhashmap.作为最重要的实现之一地图在使用方面的界面。我们还在差异方面探讨了其内部运作Hashmap.这是它的超级类。

希望在阅读这篇文章之后,您可以在您的用例中进行更多地图实现的更新和有效的决策。

可以在本文中使用的所有示例的完整源代码GitHub项目

Java底部

开始使用Spring 5和Spring Boot 2,通过学习的春天课程:

>>查看课程
评论在本文上关闭!