Java最高

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

>>看看这个课程

1.介绍

在本文中,我们将比较两个地图实施:TreeMapHashMap

这两种实现都是Java的组成部分收藏品框架和存储数据核心价值对。

2.差异

2.1。实现

我们先来谈谈雷竞技app官网网站HashMap这是一个基于散列表的实现。它扩展了AbstractMap班级和实现地图接口。一种HashMap工作原理哈希

地图实施通常充当桶哈希表, 但当存储单元太大时,它们就会转化为treenodes.,它们的结构都类似于java.util.TreeMap。

你可以在Hashmap内部的这篇文章聚焦于此

另一方面,TreeMap延伸AbstractMap课程和工具NavigableMap接口。一种TreeMap存储地图元素红黑树,这是一个自动平衡二叉搜索树

而且,您也可以找到更多信息Treemp的内部的本文将重点放在这里

2.2。订单

HashMap控件中元素的排列方式不提供任何保证地图

这意味着,我们不能在迭代时假设任何订单A.HashMap

@test public void wheninsertobjectshashmap_thenrandomorder(){map  hashmap = new hashmap <>();hashmap.put(3,“treemap”);hashmap.put(2,“vs”);hashmap.put(1,“hashmap”);asserthat(hashmap.keyset(),包含inanyorder(1,2,3));}

但是,aTreeMap按自然顺序分类

如果TreeMap无法根据自然顺序对对象进行排序,然后我们可以使用a比较器可比定义元素排列的顺序地图:

@Test public void whenInsertObjectsTreeMap_thenNaturalOrder() {Map treemap = new treemap <>();treemap。把(3“TreeMap”);treemap。把(2中,“和”);treemap。把(HashMap);断言(tremap . keyset(),包含(1,2,3));}

2.3。

HashMap允许最多存放钥匙和许多人价值观。

让我们看看一个例子:

@Test public void whenInsertNullInHashMap_thenInsertsNull() {Map hashmap = new hashmap <>();hashmap。把(空,空);assertNull (hashmap.get (null));}

然而,TreeMap不允许一个钥匙但可能包含很多价值观。

一种键不被允许,因为相比于()或者是compare ()方法抛出A.空指针异常:

@test(预期= nullpointerexception.class)public void wheninsertnullintreemap_thenexception(){map <整数,字符串> treemap = new triemap <>();triemap.put(null,nullpointerexception“);}

如果我们正在使用TreeMap使用用户定义比较器,则取决于比较的实现()方法如何值处理。

3.性能分析

性能是最关键的指标,帮助我们了解给定使用案例的数据结构的适用性。

在本节中,我们将为绩效提供全面的分析HashMapTreeMap。

3.1。HashMap

Hashmap,作为一个基于散列表的实现,内部使用基于数组的数据结构根据哈希功能

HashMap提供预期的固定时间性能O (1)对于大多数操作,如添加()remove ()包含()。因此,它明显快于TreeMap

在哈希表中,在合理的假设下搜索元素的平均时间是o(1)。但是,实施不当的实施哈希功能可能导致桶中的值差,这导致:

  • 记忆开销 - 许多桶仍未使用
  • 性能下降-碰撞次数越多,性能越低

在Java 8之前,单独的链接是处理冲突的唯一首选方法。它通常使用链接列表来实现,IE。,如果有任何碰撞或两个不同的元素具有相同的哈希值,则将项目存储在同一链接列表中。

因此,在Hashmap,在最坏的情况下,只要在链接列表中搜索元素IE。上)时间。

但是,有了19EP 180.进入图片,实现了元素排列的方式的微妙变化Hashmap。

根据规范,当桶变得太大并且包含了足够多的节点时,它们就会转换为模式treenodes.,它们的结构都类似于TreeMap

因此,在发生高哈希冲突的情况下,最坏情况下的性能将从上)O (log n)。

执行此转换的代码已被说明:

if(bincount> = treeify_threshold  -  1){treeifybin(tab,哈希);}

价值TREEIFY_THRESHOLD是八个,有效地表示使用树的阈值计数而不是桶的链接列表。

很明显:

  • 一种HashMap需要更多的内存,而不是保持其数据
  • 一种HashMap不应该超过70% - 75%满。如果它接近,就会调整大小并重新散列条目
  • 再处理要求N在此操作中,我们的常数时间插入变得有序上)
  • 是哈希算法决定了对象插入的顺序HashMap

表现的HashMap可以通过设置自定义来调整吗最初的产能负荷系数, 在那个时间HashMap对象创建本身。

然而,我们应该选择HashMap如果:

  • 我们大概知道在我们的集合中要保留多少项
  • 我们不想按自然顺序提取物品

在上述情况下,HashMap是我们最好的选择,因为它提供固定的时间插入,搜索和删除。

3.2。TreeMap

一种TreeMap将其数据存储在分层树中,其能够在自定义的帮助下对元素进行排序比较器。

其表现总结如下:

  • TreeMap提供性能o(日志(n))对于大多数操作,如添加()remove ()包含()
  • 一种Treemap可以节省内存(相比Hashmap)因为它只使用存储项目所需的内存量,不像HashMap哪个使用连续的内存区域
  • 一棵树应该保持其平衡,以保持其预期的性能,这需要大量的努力,因此使实施变得复杂

我们应该去TreeMap每当:

  • 必须考虑记忆局限性
  • 我们不知道内存中必须存储多少项
  • 我们希望以自然的顺序提取对象
  • 如果项目将一致添加和删除
  • 我们愿意接受O (log n)搜索时间

4.相似之处

4.1。独特的元素

这两个TreeMapHashMap不支持重复的键。如果添加,它将覆盖前面的元素(没有错误或异常):

@Test public void givenHashMapAndTreeMap_whenputDuplicates_thenOnlyUnique() {Map treeMap = new HashMap<>();treeMap。把(1、“Bae雷竞技app下载官方版isoldung”);treeMap。把(1、“Bae雷竞技app下载官方版isoldung”);assertTrue (treeMap.size () = = 1);Map treeMap2 = new TreeMap<>();treeMap2。把(1、“Bae雷竞技app下载官方版isoldung”);treeMap2。put(1, "Baeldung"); assertTrue(treeMap2.size() == 1); }

4.2。并发访问

这两个地图实施不是同步我们需要自己管理并发访问。

当多个线程同时访问它们并且至少有一个线程修改它们时,它们都必须从外部同步。

我们必须明确使用集合.synchronizedmap(mapName)要获取提供的地图的同步视图。

4.3。快速失败迭代器

迭代器抛出一个ConcurrentModificationException.如果是地图一旦创建迭代器,就以任何方式和任何时间进行修改。

此外,我们可以使用迭代器的remove方法来更改地图在迭代期间。

让我们看看一个例子:

@test public void whenmodifymapduringiteration_thenthrowexecption(){map <整数,字符串> hashmap = new hashmap <>();hashmap.put(1,“一”);hashmap.put(2,“二”);可执行的可执行文件=() - > hashmap .foreach((key,value) - > hashmap.remove(1));断言(ConcurrentModificationException.class,可执行文件);}

5.使用哪个实现?

一般来说,两种实现都有各自的优缺点,但是,这是关于了雷竞技app官网网站解必须管理我们选择的潜在期望和要求。

总结:

  • 我们应该使用一个TreeMap如果我们想保持条目的排序
  • 我们应该使用一个HashMap如果我们优先考虑性能而不是内存消耗
  • 自A.TreeMap有一个更重要的局部性,如果我们想要访问根据它们的自然顺序彼此相对接近的对象,我们可以考虑它
  • HashMap可以使用initialCapacity.loadfactor.,这是不可能的TreeMap
  • 我们可以使用LinkedHashMap如果我们想保持插入顺序,同时受益于固定的时间访问

6.结论

在本文中,我们展示了差异和相似之处TreeMapHashMap

与始终一样,本文的代码示例可用在GitHub

Java底部

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

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