Java 是否有一种有效的方法来检查HashMap是否包含映射到相同值的键?

Java 是否有一种有效的方法来检查HashMap是否包含映射到相同值的键?,java,hashmap,Java,Hashmap,我基本上需要知道我的HashMap是否有映射到相同值的不同键。我想知道是否有一种方法,除了对照地图中的所有其他值检查每个键的值之外 更新: 只是一些更多的信息,希望能澄清我想要实现的目标。考虑一个字符串AZZA。假设我迭代这个字符串并将每个字符存储为一个键,它对应的值是其他字符串。假设我最终找到了“a”的最后一个匹配项,并且该值已经在映射中。如果与映射中已经存在的值对应的键也为“a”,那么这就可以了。当“a”和“z”都映射到同一个值时,就会出现我的问题。仅当不同的键映射到相同的值时。您可以创建一

我基本上需要知道我的HashMap是否有映射到相同值的不同键。我想知道是否有一种方法,除了对照地图中的所有其他值检查每个键的值之外

更新: 只是一些更多的信息,希望能澄清我想要实现的目标。考虑一个字符串AZZA。假设我迭代这个字符串并将每个字符存储为一个键,它对应的值是其他字符串。假设我最终找到了“a”的最后一个匹配项,并且该值已经在映射中。如果与映射中已经存在的值对应的键也为“a”,那么这就可以了。当“a”和“z”都映射到同一个值时,就会出现我的问题。仅当不同的键映射到相同的值时。

您可以创建一个哈希映射,将值映射到键列表。这将占用更多的空间,并且需要稍微复杂一些的代码,但是与循环所有值的方法相比,摊销O1的效率要高得多

Map<Integer, String> map = new HashMap<>();
Set<String> values = new HashSet<>();
Set<Integter> keysWithSameValue = new HashSet<>();

for(Integer key : map.keySet()) {
  if(values.contains(map.get(key))) {
    keysWithSameValue.add(key);
  }
  values.add(map.get(key));
}
例如,假设您当前有HashMap map1,您想知道哪些键具有相同的值。您可以创建另一个映射HashMap map2

然后您只需同时修改map1和map2

map1.put(key, value);
if(!map2.containsKey(value)) {
    map2.put(value, new ArrayList<Key>);
}
map2.get(value).add(key);
然后,要获取映射到value的所有键,只需执行map2.getvalue

如果您需要在许多不同的地方放置/删除,为确保您不会忘记使用map2,您可以创建自己的数据结构,即一个包含2个映射的单独类,并为此实现放置/删除/获取/等


编辑:我可能误解了这个问题。如果您不需要实际的键列表,只需要简单的是/否回答映射是否已经包含此值?并且您想要比On更好的内容,那么您可以保留一个单独的HashMap,该HashMap只计算值在映射中出现的次数。这比列表映射占用的空间要小得多。

您可以迭代键并将当前值保存在集合中。 但是,在将该值插入集合之前,请检查集合是否已包含该值

如果这是真的,则表示上一个键已包含相同的值

Map<Integer, String> map = new HashMap<>();
Set<String> values = new HashSet<>();
Set<Integter> keysWithSameValue = new HashSet<>();

for(Integer key : map.keySet()) {
  if(values.contains(map.get(key))) {
    keysWithSameValue.add(key);
  }
  values.add(map.get(key));
}

当然,编码和执行的最快速度是:

boolean hasDupeValues = new HashSet<>(map.values()).size() != map.size();
它按时执行


集合不允许重复,因此,如果存在重复,集合将小于值列表。

与上面EJP和Bohemian的答案非常相似,但有流:

boolean hasDupeValues = map.values().stream().distinct().count() != map.size();

您可以通过调用map.values.containsvalue来检查映射是否已经包含值。这并不像在地图中查找键那样有效,但它仍然处于启用状态,并且您不需要创建一个新的集合来计算其元素

然而,您似乎需要的是一个BiMap。Java标准库中没有这样的东西,但是您可以通过使用两个HashMap相对容易地构建一个:一个将键映射到值,另一个将值映射到键。每次将一个键映射到一个值时,都可以在摊销O1中检查该值是否已映射到,如果未映射到,则将该键映射到一个映射中的值,将该值映射到另一个映射中的键


如果可以为项目创建新的依赖项,则某些第三方库包含现成的BIMAP,如Guava和Apache Commons。

获取值集合,将其转换为哈希集,然后查看集合大小是否小于值集合大小。这假设值对象具有合适的equals和hashCode实现。仔细考虑后,我认为如果不简单地将每个值与所有其他值进行比较,我就不可能完成我试图完成的任务。例如,如果我有字符串dddd。当我迭代该字符串并将每个字符映射到其他字符串时,如果所有出现的“d”都映射到一个值,例如apples,这就可以了。我的地图将以一个键和一个值结束。只有当像ddad这样的东西和'a'和'd'都映射到应用程序时,我们才可以使用ConcurrentHashMap中的putIfAbsent方法。我们可以检查返回值-如果它与null不同,我们将它添加到KeysWithSameValues中。我也考虑过这一点。问题是,当我向映射添加键和值时,可能会遇到我已经添加的键值对。集合会告诉我,我有一个问题,因为值已经出现了,但实际上,我用同一对添加相同的键对于我正在尝试的操作来说是很好的。我从来都不知道这个putIfAbsent方法!谢谢根据我提到的警告,我最终使用了你和EJP提到的一个集合,我只是需要使用一些有条件的创造性。谢谢不过,如果HashMaps有一个.containsValue方法,那就太酷了。这正是我所希望的,一个具有这样一个函数的库,这样我就不必在集合中使用额外的空间了。@ElroyJetson什么使你认为HashMap没有containsValue方法?@LouisWasserman的修辞q
尽管如此,如何包含价值帮助?当然,对于每个值,它都会返回true,因此查找重复项是没有用的。在每次插入前使用该选项可能有助于防止重复,但您询问了查找重复项的问题。是的,在插入前使用该选项会很有用,我同意我的问题可以表述得更好。是的,我只需要一个简单的“是”或“否”。我更新了我的问题,我开始认为没有其他方法可以实现我想要实现的目标。map.values.containsvalue与map.containsvalue完全等价。