Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java, what precautions should be taken when using a Set as a key in a Map?

Tags:

java

set

map

I'm not sure what are prevailing opinions about using dynamic objects such as Sets as keys in Maps.

I know that typical Map implementations (for example, HashMap) use a hashcode to decide what bucket to put the entry in, and that if that hashcode should change somehow (perhaps because the contents of the Set should change at all, then that could mess up the HashMap by causing the bucket to be incorrectly computed (compared to how the Set was initially inserted into the HashMap).

However, if I ensure that the Set contents do not change at all, does that make this a viable option? Even so, is this approach generally considered error-prone because of the inherently volatile nature of Sets (even if precautions are taken to ensure that they are not modified)?

It looks like Java allows one to designate function arguments as final; this is perhaps one minor precaution that could be taken?

Do people even do stuff like this in commercial/open-source practice? (put List, Set, Map, or the like as keys in Maps?)

I guess I should describe sort of what I'm trying to accomplish with this, so that the motivation will become more clear and perhaps alternate implementations could be suggested.

What I am trying to accomplish is to have something of this sort:

class TaggedMap<T, V> {
  Map<Set<T>, V> _map;
  Map<T, Set<Set<T>>> _keys;
}

...essentially, to be able to "tag" certain data (V) with certain keys (T) and write other auxiliary functions to access/modify the data and do other fancy stuff with it (ie. return a list of all entries satisfying some criteria of keys). The function of the _keys is to serve as a sort of index, to facilitate looking up the values without having to cycle through all of _map's entries.

In my case, I intend to specifically use T = String, V = Integer. Someone I talked to about this had suggested substituting a String for the Set, viz, something like:

class TaggedMap<V> {
  Map<String, V> _map;
  Map<T, Set<String>> _keys;
}

where the key in _map is of the sort "key1;key2;key3" with keys separated by delimiter. But I was wondering if I could accomplish a more generalised version of this rather than having to enforce a String with delimiters between the keys.

Another thing I was wondering was whether there was some way to make this as a Map extension. I was envisioning something like:

class TaggedMap<Set<T>, V> implements Map<Set<T>, V> {
  Map<Set<T>, V> _map;
  Map<T, Set<Set<T>>> _keys;
}

However, I was not able to get this to compile, probably due to my inferior understanding of generics. With this as a goal, can anyone fix the above declaration so that it works according to the spirit of what I had described or suggest some slight structural modifications? In particular, I am wondering about the "implements Map, V>" clause, whether it is possible to declare such a complex interface implementation.

like image 948
omnilinguist Avatar asked Aug 10 '11 07:08

omnilinguist


People also ask

Can a Set be a key for map in Java?

HashMap. keySet() method in Java is used to create a set out of the key elements contained in the hash map. It basically returns a set view of the keys or we can create a new set and store the key elements in them. Parameters: The method does not take any parameter.

What should you do when using a custom Java object as a key in a map?

Therefore, to use an object as a key in HashMap , HashSet , or Hashtable in Java, we need to override equals and hashcode methods of that object since default implementation of these methods simply check for the instance equality.

What are the things need to take care when HashMap with custom object as key?

To put it simply, we have to ensure that the hashCode() method returns: the same value for the object as long as the state doesn't change (Internal Consistency) the same value for objects that are equal (Equals Consistency) as many different values as possible for objects that are not equal.

What happens if we put a key object in a HashMap which exists?

What happens if we put a key object in a HashMap which exists? Explanation: HashMap always contains unique keys. If same key is inserted again, the new object replaces the previous object.

How to implement map in Java?

There are two interfaces for implementing Map in java: Map and SortedMap, and three classes: HashMap, LinkedHashMap, and TreeMap. The hierarchy of Java Map is given below: A Map doesn't allow duplicate keys, but you can have duplicate values. HashMap and LinkedHashMap allow null keys and values, but TreeMap doesn't allow any null key or value.

How do you get key values from a map in Java?

Get Keys and Values (Entries) from Java Map Most of the time, you're storing key-value pairs because both pieces of info are important. Thus, in most cases, you'll want to get the key-value pair together. The entrySet () method returns a set of Map.Entry<K, V> objects that reside in the map.

What is the use of key value store in Java?

Key-value stores are essential and often used, especially in operations that require fast and frequent lookups. They allow an object - the key - to be mapped to another object, the value. This way, the values can easily be retrieved, by looking up the key. In Java, the most popular Map implementation is the HashMap class.

What is the difference between set and map in Java?

The main difference between Set and Map is that Set contains only data elements, and the Map contains the data in the key-value pair, so Map contains key and its value. Now, let's understand some major differences between both of them.


1 Answers

You are correct that if you ensure that

  1. The Set contents are not modified, and
  2. The Sets themselves are not modified

That it is perfectly safe to use them as keys in a Map.

It's difficult to ensure that (1) is not violated accidentally. One option might be to specifically design the class being stored inside the Set so that all instances of that class are immutable. This would prevent anyone from accidentally changing one of the Set keys, so (1) would not be possible. For example, if you use a Set<String> as a key, you don't need to worry about the Strings inside the Set changing due to external modification.

You can make (2) possible quite easily by using the Collections.unmodifiableSet method, which returns a wrapped view of a Set that cannot be modified. This can be done to any Set, which means that it's probably a very good idea to use something like this for your keys.

Hope this helps! And if your user name means what I think it does, good luck learning every language! :-)

like image 108
templatetypedef Avatar answered Sep 22 '22 05:09

templatetypedef