简体   繁体   中英

Is there an efficient way of checking if HashMap contains keys that map to the same value?

I basically need to know if my HashMap has different keys that map to the same value. I was wondering if there is a way other than checking each keys value against all other values in the map.

Update: Just some more information that will hopefully clarify what I'm trying to accomplish. Consider a String "azza". Say that I'm iterating over this String and storing each character as a key, and it's corresponding value is some other String. Let's say I eventually get to the last occurrence of 'a' and the value is already be in the map.This would be fine if the key corresponding with the value that is already in the map is also 'a'. My issue occurs when 'a' and 'z' both map to the same value. Only if different keys map to the same value.

Sure, the fastest to both code and execute is:

boolean hasDupeValues = new HashSet<>(map.values()).size() != map.size();

which executes in O(n) time.

Sets don't allow duplicates, so the set will be smaller than the values list if there are dupes.

You could create a HashMap that maps values to lists of keys. This would take more space and require (slightly) more complex code, but with the benefit of greatly higher efficiency (amortized O(1) vs. O(n) for the method of just looping all values).

For example, say you currently have HashMap<Key, Value> map1 , and you want to know which keys have the same value. You create another map, HashMap<Value, List<Key>> map2 .

Then you just modify map1 and map2 together.

map1.put(key, value);
if(!map2.containsKey(value)) {
    map2.put(value, new ArrayList<Key>);
}
map2.get(value).add(key);

Then to get all keys that map to value , you just do map2.get(value) .

If you need to put/remove in many different places, to make sure that you don't forget to use map2 you could create your own data structure (ie a separate class) that contains 2 maps and implement put/remove/get/etc. for that.


Edit: I may have misunderstood the question. If you don't need an actual list of keys, just a simple "yes/no" answer to "does the map already contain this value?", and you want something better than O(n), you could keep a separate HashMap<Value, Integer> that simply counts up how many times the value occurs in the map. This would take considerably less space than a map of lists.

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

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

You can check whether a map contains a value already by calling map.values().contains(value) . This is not as efficient as looking up a key in the map, but still, it's O(n), and you don't need to create a new set just in order to count its elements.

However, what you seem to need is a BiMap . There is no such thing in the Java standard library, but you can build one relatively easily by using two HashMap s: one which maps keys to values and one which maps values to keys. Every time you map a key to a value, you can then check in amortized O(1) whether the value already is mapped to, and if it isn't, map the key to the value in the one map and the value to the key in the other.

If it is an option to create a new dependency for your project, some third-party libraries contain ready-made bimaps, such as Guava ( BiMap ) and Apache Commons ( BidiMap ).

You could iterate over the keys and save the current value in the Set. But, before inserting that value in a Set, check if the Set already contains that value.

If this is true, it means that a previous key already contains the same value.

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));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM