是否将重复的值添加到HashSet / HashMap会替换先前的值


137

请考虑以下代码:

HashSet hs = new HashSet();
hs.add("hi"); -- (1)
hs.add("hi"); -- (2)

hs.size()将给出1,因为HashSet不允许重复,因此将只存储一个元素。

我想知道是否要添加重复元素,然后它会替换前一个元素还是根本不添加它?

另外,HashMap在相同情况下使用会发生什么?

Answers:


246

对于HashMap,它将用新值替换旧值。

如果是HashSet,则不会插入该项目。


1
不知道我缺少什么,但是源代码似乎表明其他情况?我看到他们在调用支持之前不检查支持HashMap是否key已存在?putmap
mystarrocks 2014年

10
@mystarrocks:密钥是的元素Set,并且永远不会被put()操作取代。
开普勒2014年

1
啊,我明白了。我知道键是的元素Set,但刚刚意识到那只put()会覆盖值,而不是键。在这种情况下,再次将相同的值放在键旁边,这可能比检查键是否存在并放置更好,也可能不会更好。无论哪种方式,我都知道它是如何工作的。
mystarrocks 2014年

只是好奇,为什么HashMap和HashSet选择是这样?
Helin Wang

@HelinWang:我不认为这是计划好的,我认为这只HashSet是以的形式实现的效果HashMap。但是,除非您是此类的开发人员之一,否则很难知道。
开普勒2014年

47

您需要了解的第一件事是,它的HashSet行为类似于Set,这意味着您将对象直接添加到中,HashSet并且该对象不能包含重复项。您只需直接在中添加值即可HashSet

但是,HashMap是一种Map。这意味着每次添加条目时,都会添加一个键值对。

输入中HashMap可以有重复的值,但不能有重复的键。在HashMap新条目中将替换旧条目。最近的条目将在中HashMap

了解HashMap和HashSet之间的链接:

记住,HashMap不能有重复的密钥。幕后HashSet使用HashMap

当您尝试将任何对象添加到中时HashSet,该条目实际上被存储为-中的键,与HashMap- HashMap幕后使用的键相同HashSet。由于此基础HashMap需要键值对,因此会为我们生成一个虚拟值。

现在,当您尝试将另一个重复的对象插入同一对象时HashSet,它将再次尝试将其作为钥匙插入HashMap下面。但是,HashMap不支持重复。因此,HashSet仍将导致仅具有该类型的一个值。附带说明一下,对于每个重复的密钥,由于在HashSet中为我们的条目生成的值是某个随机值/虚拟值,因此根本不会替换该密钥。它会被忽略,因为删除键并添加相同的键(伪值相同)根本没有任何意义。

摘要:

HashMap允许重复values,但不允许重复keysHashSet不能包含重复项。

要了解对象的添加是否成功完成,可以检查boolean调用时返回的值,.add() 并查看它是否返回truefalse。如果返回true,则将其插入。


HashMap allows duplicate valuesHashMap用新值替换了旧值。
Alex78191

20

文档是对这个很清楚:HashSet.add 更换:

如果指定的元素尚不存在,则将其添加到该集合中。更正式地说,如果此元素集中不包含任何元素e2,则将指定元素e添加到该元素集合中,使得(e == null?e2 == null:e.equals(e2))。如果此集合已包含该元素,则调用将使该集合保持不变并返回false。

替换为:HashMap.put

如果该映射先前包含该键的映射,则将替换旧值。



1

如果我错了,请纠正我,但是您得到的是字符串,“ Hi” ==“ Hi”并不总是正确的(因为它们不一定是同一个对象)。

答案为1的原因是因为JVM将尽可能重用字符串对象。在这种情况下,JVM将重用字符串对象,从而覆盖Hashmap / Hashset中的项目。

但是您不能保证这种行为(因为它可能是具有相同值“ Hi”的另一个字符串对象)。您看到的行为仅仅是由于JVM的优化。


0

您首先需要检查Hash映射中的put方法,因为HashSet由HashMap备份

  1. 当您添加重复值时,在HashSet中说一个字符串“ One”,
  2. 一个条目(“ one”,PRESENT)将被插入到Hashmap中(对于添加到集合中的所有值,该值将为“ PRESENT”,如果为Object类型,则为“ PRESENT”)
  3. Hashmap将条目添加到Map中并返回值,在这种情况下,该值为“ PRESENT”;如果没有Entry,则为null。
  4. 如果Hashmap返回的值等于null,则Hashset的add方法返回true,否则返回false,这意味着条目已经存在。

0

换句话说:当您将键值对插入已经存在键的HashMap中时(在某种意义上,hashvalue()给出相同的值,而equal()为true,但是两个对象仍然可以在几种方式上有所不同) ),则不会替换键,但值会被覆盖。该键仅用于获取hashvalue()并与其一起在表中查找值。由于HashSet使用HashMap的键并设置对用户而言实际上并不重要的任意值,因此Set的Elements也不会被替换。


0

HashMap基本上包含Entry随后包含Key(Object)和的内容Value(Object)。正如某些人已经指出的那样,内部HashSetHashMapand HashMap确实替换值。但是它确实替换了键吗?HashMap保持其值作为基础中的键,HashMap而值只是一个伪对象。因此,如果您尝试在HashMap(基础Map中的键)中重新插入相同的Value,它将替换伪值而不是Key(HashSet的值)。

查看下面的HashSet类代码:

public boolean  [More ...] add(E e) {

   return map.put(e, PRESENT)==null;
}

这里e是HashSet的值,但是基础map。的键,而键永远不会被替换。希望我能消除混乱。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.