Java Top.

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

>>查看课程

1.概述

在本文中,我们将深入研究哈希集。这是最受欢迎的实现以及Java集合框架的一个组成部分。

2.介绍HashSet

HashSet是Java Collections API中的基本数据结构之一

让我们回顾一下这个实现中最重要的方面:

  • 它存储惟一元素并允许为空
  • 它的后面是aHashmap.
  • 它不维护插入顺序
  • 它不是线程安全的

请注意,这内部Hashmap.控件的实例时初始化HashSet被建造:

public HashSet() {map = new HashMap<>();}

如果你想深入了解如何Hashmap.作品,你可以阅读这篇文章的重点是在这里

3.API.

在这一节中,我们将回顾最常用的方法,并看一些简单的例子。

3.1。add ()

add ()方法可用于将元素添加到集合中。该方法合同指出,仅当它尚未存在于一组中时,才会添加元素。如果添加了一个元素,则该方法返回真的,除此以外 -错误的。

我们可以为a添加一个元素HashSet喜欢:

@test public void whodddingelement_shouldddelement(){set  hashset = new hashset <>();asserttrue(hashset.add(“字符串添加”)));}

从实现的角度来看,添加方法是非常重要的。实现细节说明了如何HashSet内部工作并利用HashMap的方法:

public boolean add(E E) {return map。put(e, PRESENT) == null;}

地图变量是对内部的引用,支持HashMap:

private transient HashMap map;

熟悉一下会是个好主意哈希科特首先要详细了解如何在基于哈希的数据结构中组织元素。

总结:

  • 一个Hashmap.是一系列的默认容量为16个元素 - 每个桶对应于不同的哈希码值
  • 如果各种对象具有相同的hashcode值,则将它们存储在单个桶中
  • 如果是负载系数达到了一个新的阵列创建了前一个堆栈的大小的两倍,并且所有元素都会在新的相应存储桶中重新分配和重新分发
  • 要检索一个值,我们哈希一键,mod它,然后转到相应的桶并在存在多个对象的情况下通过潜在的链接列表搜索

3.2。包含()

该计划的目的包含方法是检查给定元素中是否存在元素HashSet它返回真的如果找到该元素,否则错误的。

我们可以检查一个元素HashSet

@test public vod whetcheckingforement_shouldsearchforement(){set  hashsetContains = new hashset <>();hashsetContains.add(“添加”);asserttrue(hashsetContains.Contains(添加“字符串”));}

每当将对象传递给此方法时,就会计算散列值。然后,解析并遍历相应的桶位置。

3.3。去掉()

如果指定的元素存在,则该方法将其从集合中移除。该方法返回真的如果设置包含指定的元素。

让我们看看一个工作示例:

@Test public void whenRemovingElement_shouldRemoveElement() {Set removeFromHashSet = new HashSet<>();removeFromHashSet。添加("String Added"); assertTrue(removeFromHashSet.remove("String Added")); }

3.4。清除()

当我们打算从集合中删除所有项目时,我们使用此方法。底层实施简单地清除了底层的所有元素HashMap。

让我们来看看它的实际应用:

@Test public void whenClearingHashSet_shouldClearHashSet() {Set clearHashSet = new HashSet<>();clearHashSet。添加("String Added"); clearHashSet.clear(); assertTrue(clearHashSet.isEmpty()); }

3.5。尺寸()

这是API中的基本方法之一。它被大量使用,因为它有助于识别元素中存在的数量HashSet.底层实施只是将计算委托给了hashmap的大小()方法。

让我们来看看它的实际应用:

@Test public void whenCheckingTheSizeOfHashSet_shouldReturnThesize() {Set hashSetSize = new HashSet<>();hashSetSize。添加("String Added"); assertEquals(1, hashSetSize.size()); }

3.6。isEmpty ()

我们可以使用此方法来定位一个给定的a的实例HashSet是空的。该方法返回真的如果集合中不包含元素:

@test公共vod whetcheckingforemptyhashset_shouldcheckforempty(){set  emptyhashset = new hashset <>();asserttrue(emptyhashset.isusempty());}

3.7。迭代器()

对象中的元素返回一个迭代器元素的访问没有特定的顺序,迭代器是快速失败的

我们可以在此处观察随机迭代顺序:

@test公共void whinitoringhashset_shoulditeratehashset(){set  hashset = new hashset <>();hashset.add(“第一”);hashset.add(“第二”);hashset.add(“第三”);Iterator itr = hashset.iterator();while(iTr.hasnext()){system.out.println(iTr.next());}}

如果该集合在迭代器创建后的任何时间以除通过迭代器自己的remove方法之外的任何方式被修改,则迭代器抛出A.并发修改异常

让我们来看看它的实际应用:

@Test(expected = ConcurrentModificationException.class) public void whenModifyingHashSetWhileIterating_shouldThrowException() {Set hashset = new hashset <>();hashset.add(“第一”);hashset.add(“第二”);hashset.add(“第三”);Iterator itr = hashset.iterator();while (itr.hasNext()) {itr.next();hashset.remove(“第二”);}}

或者,如果我们使用了迭代器的remove方法,那么我们就不会遇到异常:

@test public void whyremovingelementusing sitterator_shouldremoveelement(){set  hashset = new hashset <>();hashset.add(“第一”);hashset.add(“第二”);hashset.add(“第三”);Iterator itr = hashset.iterator();while(iTr.hasnext()){string元素= iTr.next();if(emport.equals(“第二”))ITR.Remove();} assertequals(2,hashset.size());}

迭代器的快速失败行为无法得到保证,因为在存在非同步并发修改的情况下不可能做出任何硬保证。

失败快速迭代器投掷并发修改异常以尽力而为。因此,写一个依赖于这个例外的程序是错误的。

4.如何HashSet保持唯一性?

当我们将物体放入一个HashSet,它使用对象的哈希科特值以确定元素是否不在集合中。

每个哈希码值对应某个bucket位置,bucket位置可以包含各种元素,计算出的哈希值是相同的。但是两个物体是一样的hashCode可能不相等

因此,将使用相同桶中的对象使用等于()方法。

5.表现HashSet

a的性能HashSet主要受两个参数的影响——其初始容量负荷系数

将元素添加到集合的预期时间复杂度是O(1)可以掉进O (n)在最坏的情况下(只有一个桶)-因此,维护权利是必要的哈希集能力。

一个重要的注意:自JDK 8以来,最坏的情况是时间复杂度o(log * n)

负载因子描述的是最大填充水平,超过这个水平,一组将需要调整大小。

我们也可以创造一个HashSet具有自定义值初始容量负载系数

set  hashset = new hashset <>();set  hashset = new hashset <>(20);set  hashset = new hashset <>(20,0.5f);

在第一种情况下,使用默认值-初始容量16和负载因子0.75。在第二个例子中,我们覆盖了默认容量,在第三个例子中,我们覆盖了两个。

较低的初始容量降低了空间复杂度,但增加了重散列的频率,这是一个昂贵的过程。

另一方面,高初始容量增加了迭代的成本和初始内存消耗。

作为一个经验法则:

  • 高初始容量对于大量条目加上很少甚至没有迭代是好的
  • 初始容量低很少有很多迭代的条目

因此,在这两者之间找到正确的平衡是非常重要的。通常情况下,默认实现是经过优化的,工作正常,如果我们觉得需要调优这些参数以满足需求,我们需要明智地做。

六,结论

在本文中,我们概述了aHashSet,它的目的和基本工作。我们看到了它在可用性方面的效率,因为它具有恒定的时间性能和避免重复的能力。

我们研究了API中的一些重要方法,他们如何帮助我们作为开发人员使用HashSet其潜力。

和往常一样,可以找到代码片段在github上

Java底部

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

>>查看课程
2注释
最古老的
最新的
内联反馈
查看所有评论
对这篇文章的评论关闭!