Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Keys to Single Value Map Java

Tags:

I think my question is similar to this one: How to implement a Map with multiple keys? but with an important difference. In that question (if my understanding of it is correct, please let me know if it isn't), the keys were supposed to always be unique. I want to have a Map in the form: MyMap where the keys aren't necessarily unique. If that doesn't make sense, I basically want a 2 dimensional array, but rather than refering to elements by coordinates, I want to refer to them by pairs of objects.

Anyone have any ideas as to either a library where this works or a good way to implement this myself? As far as libraries go, I've looked at Apache Commons and Guava, neither seem to have what I want.

like image 552
Steve Avatar asked Jul 20 '11 21:07

Steve


People also ask

Can 2 keys have same value in map?

However, none of the existing Java core Map implementations allow a Map to handle multiple values for a single key. As we can see, if we try to insert two values for the same key, the second value will be stored, while the first one will be dropped.

Can a map have multiple keys Java?

We can also use Apache Commons Collection, which provides an efficient map implementation MultiKeyMap that maps multiple keys to a value. MultiKeyMap provides get, containsKey, put, and remove for individual keys.

Can two keys have the same value Java?

Java HashMap stores references to Objects. If you store same object with two different keys, the keys will point to the same value.

Can a HashMap have two keys?

You can't have an hash map with multiple keys, but you can have an object that takes multiple parameters as the key.


2 Answers

The Table data structure in Guava seems to meet you requirement of refering to a value by a pair of objects.

like image 163
Mark Avatar answered Oct 27 '22 02:10

Mark


I hope this answer won't be seen as a rant, but as far as I could understand, you want to use a library for something that you can achieve in a trivial way using a jdk out of the box.

Anyway, you mentioned that you want to access elements using a pair of objects. You could create a class that will hold the keys, such as

public class Pair {
  // string represntation of an object
  private final String x; 
  private final String y;

  // ctor, getters...

  public int hashcode() {...}
  public boolean equals(Object other) {...}
}

The hashcode method will generate the hashcode for all comprising elements (in this case, two, xand y in your case, but can be easily extended to support an arbitrary number of elements), and two keys will be the same if they have the same values for xand y. If your pair elements are not simple strings, it is trivial to derive a string representation of almost any object (provide a decent implementation of the toString method, for instance).

The idea is to have a unique string representation for each element in the pair.

Of course, generating solid hashcodes is not trivial, so an excellent option isto use Strings. To generate a hashcode, you would simply append the string representations of your pair objects:

public int hashcode() {
  return ('x' + x + ":y" + y).hashcode();
}

Be sure to provide some separator. Otherwise, for values such as x=ab, y=b, and x=a, y=bb, you'll get the same hashcode, even if the objects are completely different.

And equality is as trivial as inspecting the value of the elements in the pair:

public boolean equals(Object other) {
  // if other is not null and is an instance of Pair
  final Pair otherPair = (Pair)other;
  return this.x.equals(otherPair.x) && this.y.equals(otherPair.y);
}

So, now you could use your Pairclass in a map, such as in:

final Map<Pair, Whatever> map = new Hashmap<Pair, Whatever>();
// ...

Basicaly, a hashmap works by using the hashcode of the keys to determine in which bucket the value should be allocated. If two keys have the same hashcode, then the equals method will be used to determine if a collision just occurred, or if it's just the same key.

If you want to use your Pair class in a TreeMap, you would have to implement the compareTo method, or provide your own Comparator when instantiating such a map. TreeMap implementations rely on the result of the compareTo method to determine where a value should be allocated.

like image 29
chahuistle Avatar answered Oct 27 '22 02:10

chahuistle