149

请考虑以下代码:

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

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

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

另外,同样的情况会发生什么HashMap

4

8 回答 8

265

在 的情况下HashMap,它将旧值替换为新值。

在 的情况下HashSet,不插入项目。

于 2012-10-17T18:14:55.927 回答
54

您需要知道的第一件事是它的HashSet行为类似于 a 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,它被插入。

于 2012-10-17T18:22:01.100 回答
23

文档对此非常清楚:HashSet.add 取代:

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

替换:HashMap.put

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

于 2012-10-17T18:15:55.977 回答
4

在 HashSet 的情况下,它不会取代它。

从文档:

http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )

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

于 2012-10-17T18:18:00.030 回答
1

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

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

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

于 2012-10-17T18:19:25.080 回答
1

HashMap基本上包含Entry随后包含Key(Object)Value(Object).InternallyHashSet并且确实替换了一些您已经指出的值..但它真的替换了键吗???不..这就是这里的技巧HashMap。将其值保留为底层中的键,值只是一个虚拟对象。因此,如果您尝试在 HashMap 中重新插入相同的值(底层映射中的键)。它只是替换虚拟值而不是键(HashSet 的值)。HashMapHashMapHashMap

看下面的 HashSet 类代码:

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

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

这里 e 是 HashSet 的值,但底层 map.and 的键永远不会被替换。希望我能够消除混乱。

于 2017-12-03T16:49:11.320 回答
0

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

  1. 当您在 HashSet 中添加重复值时说一个字符串“One”,
  2. 一个条目(“one”,PRESENT)将被插入到 Hashmap 中(对于添加到集合中的所有值,该值将是“PRESENT”,如果是 Object 类型)
  3. Hashmap 将条目添加到 Map 并返回值,在本例中为“PRESENT”,如果条目不存在,则返回 null。
  4. 如果 Hashmap 的返回值等于 null,则 Hashset 的 add 方法返回 true,否则返回 false,这意味着条目已经存在......
于 2014-09-09T15:57:42.353 回答
0

换一种说法:当您将键值对插入到键已经存在的 HashMap 中时(从某种意义上说,hashvalue() 给出了相同的值,而 equal() 为真,但是这两个对象仍然可以在几个方面有所不同),键不会被替换,但值会被覆盖。键仅用于获取 hashvalue() 并使用它在表中查找值。由于 HashSet 使用 HashMap 的键并设置(对用户而言)并不重要的任意值,因此 Set 的元素也不会被替换。

于 2016-08-24T09:04:24.857 回答