MatiEzelQ Asked: 2020-03-22 13:17:52 +0800 CST 2020-03-22 13:17:52 +0800 CST 2020-03-22 13:17:52 +0800 CST HashSet 在内部是如何工作的? 772 正如问题所说, HashSet 如何在内部工作? 看到这段代码: HashSet<String> a = new HashSet<>(); a.add("hola"); a.add("hola"); a.add("holaa"); a.add("hola"); 另一个问题,集合如何检查添加到集合中的元素是否重复? java 2 Answers Voted Best Answer user227 2020-03-22T14:17:37+08:002020-03-22T14:17:37+08:00 正如您仅询问的那样HashSet<T>,这很简单:此类将其几乎所有功能委托给 a HashMap<T, Object>,您插入其中的对象HashSet将是内部映射的键,并将使用内部默认对象的值进行注册地图。验证元素不重复的所有逻辑都由 set 实例中使用的内部映射处理。 由于Set单个用作 a 的包装器,因此从 Java SE 6 开始,您可以从via的任何实例Map创建 a 。SetMapCollections#newSetFromMap 有关更多背景答案:执行时如何处理元素相等HashMap#put(llave, valor)?您必须首先了解处理HashMap. 它首先定义一个节点Node<K,V>来存储键/值对并HashMap维护这些节点的数组。这些节点实现了一个简单的链表。从 Java 8 开始,实现已经改变,随着地图的增长,随着时间的推移,它包含更多的值,然后节点将它们的结构从链表更改为红黑树,从而提供更好的性能。 以下是对内部使用的算法的解释HashMap#put: 获取密钥的哈希。要获得此哈希, 的值Object#hashCode。HashMap不会直接使用这个哈希的值,在这个值上它会应用另一个公式来尽可能地减少这个值。 通过检查要插入的位置是否为空(类似于arreglo[hashInterno] == null)来检查内部数组是否可以存储新对的值。 如果该框为空,则添加新的键/值对。 如果由于哈希冲突导致框不为空:两个或多个对象产生相同的哈希值(并不意味着两个对象具有相同的结果Object#hashCode),则返回框的当前节点。我们将调用节点N: 4.1。如果 key inN等于新 key via llaveActual.equals(nuevaLlave),则将存储在的当前值替换N为新值。 4.2. 如果输入的键N不等于要插入的新键并且N它具有树结构,则将导航树节点以添加新的键/值对。遵循相同的前提:如果它Nx在树中找到一个节点,其 key 等于新的 via key llaveActual.equals(nuevaLlave),则替换 in 的值Nx。如果在搜索结束时没有找到具有相同键的节点,则会将一个新节点添加到树中。 4.3. 如果输入的键N不等于新键并且具有链表结构,它将浏览链表中的所有节点,查看节点中是否有任何键等于新键。如果没有找到这样的节点,将使用新的键/值对将一个新节点添加到列表的末尾。插入后,如果链表的值大于内部阈值(在 HotSpot 中,TREEIFY_THRESHOLD等于 8),则链表将变为红黑树。 检查节点数组是否应该使用内部配置的阈值增加大小。如果是这样,它会增加它。 集合如何验证添加到集合中的元素没有重复? 按照前面的解释,HashMap它会浏览必要的节点(并不意味着它会浏览所有元素)来检查是否存在一个 key 等于新 via key 的节点Object#equals。如果它不存在并且所有搜索都已用尽,它将添加一个带有键/值信息的新节点。 M. Mariscal 2020-03-22T13:53:05+08:002020-03-22T13:53:05+08:00 它有一定的特点... 对象没有排序 此类型不支持重复值 而不是 put,使用 add 哈希集作为一个集合使用,它不是类型(键,值) 当您想要一个唯一的对象列表时,通常会使用它。 我希望这可以帮到你!
正如您仅询问的那样
HashSet<T>
,这很简单:此类将其几乎所有功能委托给 aHashMap<T, Object>
,您插入其中的对象HashSet
将是内部映射的键,并将使用内部默认对象的值进行注册地图。验证元素不重复的所有逻辑都由 set 实例中使用的内部映射处理。由于
Set
单个用作 a 的包装器,因此从 Java SE 6 开始,您可以从via的任何实例Map
创建 a 。Set
Map
Collections#newSetFromMap
有关更多背景答案:执行时如何处理元素相等
HashMap#put(llave, valor)
?您必须首先了解处理HashMap
. 它首先定义一个节点Node<K,V>
来存储键/值对并HashMap
维护这些节点的数组。这些节点实现了一个简单的链表。从 Java 8 开始,实现已经改变,随着地图的增长,随着时间的推移,它包含更多的值,然后节点将它们的结构从链表更改为红黑树,从而提供更好的性能。以下是对内部使用的算法的解释
HashMap#put
:Object#hashCode
。HashMap
不会直接使用这个哈希的值,在这个值上它会应用另一个公式来尽可能地减少这个值。arreglo[hashInterno] == null
)来检查内部数组是否可以存储新对的值。如果由于哈希冲突导致框不为空:两个或多个对象产生相同的哈希值(并不意味着两个对象具有相同的结果
Object#hashCode
),则返回框的当前节点。我们将调用节点N
:4.1。如果 key in
N
等于新 key viallaveActual.equals(nuevaLlave)
,则将存储在的当前值替换N
为新值。4.2. 如果输入的键
N
不等于要插入的新键并且N
它具有树结构,则将导航树节点以添加新的键/值对。遵循相同的前提:如果它Nx
在树中找到一个节点,其 key 等于新的 via keyllaveActual.equals(nuevaLlave)
,则替换 in 的值Nx
。如果在搜索结束时没有找到具有相同键的节点,则会将一个新节点添加到树中。4.3. 如果输入的键
N
不等于新键并且具有链表结构,它将浏览链表中的所有节点,查看节点中是否有任何键等于新键。如果没有找到这样的节点,将使用新的键/值对将一个新节点添加到列表的末尾。插入后,如果链表的值大于内部阈值(在 HotSpot 中,TREEIFY_THRESHOLD
等于 8),则链表将变为红黑树。检查节点数组是否应该使用内部配置的阈值增加大小。如果是这样,它会增加它。
按照前面的解释,
HashMap
它会浏览必要的节点(并不意味着它会浏览所有元素)来检查是否存在一个 key 等于新 via key 的节点Object#equals
。如果它不存在并且所有搜索都已用尽,它将添加一个带有键/值信息的新节点。它有一定的特点...
对象没有排序
此类型不支持重复值
而不是 put,使用 add
哈希集作为一个集合使用,它不是类型(键,值)
当您想要一个唯一的对象列表时,通常会使用它。
我希望这可以帮到你!