[java] How to create a HashMap with two keys (Key-Pair, Value)?

I have a 2D array of Integers. I want them to be put into a HashMap. But I want to access the elements from the HashMap based on Array Index. Something like:

For A[2][5], map.get(2,5) which returns a value associated with that key. But how do I create a hashMap with a pair of keys? Or in general, multiple keys: Map<((key1, key2,..,keyN), Value) in a way that I can access the element with using get(key1,key2,...keyN).

EDIT : 3 years after posting the question, I want to add a bit more to it

I came across another way for NxN matrix.

Array indices, i and j can be represented as a single key the following way:

int key = i * N + j;
//map.put(key, a[i][j]); // queue.add(key); 

And the indices can be retrevied from the key in this way:

int i = key / N;
int j = key % N;

This question is related to java hash hashmap hashcode

The answer is


we can create a class to pass more than one key or value and the object of this class can be used as a parameter in map.

import java.io.BufferedReader; 
import java.io.FileReader;
import java.io.IOException;
import java.util.*;

 public class key1 {
    String b;
    String a;
    key1(String a,String b)
    {
        this.a=a;
        this.b=b;
    }
  }

public class read2 {

private static final String FILENAME = "E:/studies/JAVA/ReadFile_Project/nn.txt";

public static void main(String[] args) {

    BufferedReader br = null;
    FileReader fr = null;
    Map<key1,String> map=new HashMap<key1,String>();
    try {

        fr = new FileReader(FILENAME);
        br = new BufferedReader(fr);

        String sCurrentLine;

        br = new BufferedReader(new FileReader(FILENAME));

        while ((sCurrentLine = br.readLine()) != null) {
            String[] s1 = sCurrentLine.split(",");
            key1 k1 = new key1(s1[0],s1[2]);
            map.put(k1,s1[2]);
        }
        for(Map.Entry<key1,String> m:map.entrySet()){  
            key1 key = m.getKey();
            String s3 = m.getValue();
               System.out.println(key.a+","+key.b+" : "+s3);  
              }  
  //            }   
        } catch (IOException e) {

        e.printStackTrace();

    } finally {

        try {

            if (br != null)
                br.close();

            if (fr != null)
                fr.close();

        } catch (IOException ex) {

            ex.printStackTrace();

        }

    }

    }

 }

Create a value class that will represent your compound key, such as:

class Index2D {
  int first, second;

  // overrides equals and hashCode properly here
}

taking care to override equals() and hashCode() correctly. If that seems like a lot of work, you might consider some ready made generic containers, such as Pair provided by apache commons among others.

There are also many similar questions here, with other ideas, such as using Guava's Table, although allows the keys to have different types, which might be overkill (in memory use and complexity) in your case since I understand your keys are both integers.


Use a Pair as keys for the HashMap. JDK has no Pair, but you can either use a 3rd party libraray such as http://commons.apache.org/lang or write a Pair taype of your own.


You could create your key object something like this:

public class MapKey {

public  Object key1;
public Object key2;

public Object getKey1() {
    return key1;
}

public void setKey1(Object key1) {
    this.key1 = key1;
}

public Object getKey2() {
    return key2;
}

public void setKey2(Object key2) {
    this.key2 = key2;
}

public boolean equals(Object keyObject){

    if(keyObject==null)
        return false;

    if (keyObject.getClass()!= MapKey.class)
        return false;

    MapKey key = (MapKey)keyObject;

    if(key.key1!=null && this.key1==null)
        return false;

    if(key.key2 !=null && this.key2==null)
        return false;

    if(this.key1==null && key.key1 !=null)
        return false;

    if(this.key2==null && key.key2 !=null)
        return false;

    if(this.key1==null && key.key1==null && this.key2 !=null && key.key2 !=null)
        return this.key2.equals(key.key2);

    if(this.key2==null && key.key2==null && this.key1 !=null && key.key1 !=null)
        return this.key1.equals(key.key1);

    return (this.key1.equals(key.key1) && this.key2.equals(key2));
}

public int hashCode(){
    int key1HashCode=key1.hashCode();
    int key2HashCode=key2.hashCode();
    return key1HashCode >> 3 + key2HashCode << 5;
}

}

The advantage of this is: It will always make sure you are covering all the scenario's of Equals as well.

NOTE: Your key1 and key2 should be immutable. Only then will you be able to construct a stable key Object.


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

Create an object called Index that takes an x and y value.

public class Index {

    private int x;
    private int y;

    public Index(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public int hashCode() {
        return this.x ^ this.y;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Index other = (Index) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }
}

Then have your HashMap<Index, Value> to get your result. :)


Two possibilities. Either use a combined key:

class MyKey {
    int firstIndex;
    int secondIndex;
    // important: override hashCode() and equals()
}

Or a Map of Map:

Map<Integer, Map<Integer, Integer>> myMap;

When you create your own key pair object, you should face a few thing.

First, you should be aware of implementing hashCode() and equals(). You will need to do this.

Second, when implementing hashCode(), make sure you understand how it works. The given user example

public int hashCode() {
    return this.x ^ this.y;
}

is actually one of the worst implementations you can do. The reason is simple: you have a lot of equal hashes! And the hashCode() should return int values that tend to be rare, unique at it's best. Use something like this:

public int hashCode() {
  return (X << 16) + Y;
}

This is fast and returns unique hashes for keys between -2^16 and 2^16-1 (-65536 to 65535). This fits in almost any case. Very rarely you are out of this bounds.

Third, when implementing equals() also know what it is used for and be aware of how you create your keys, since they are objects. Often you do unnecessary if statements cause you will always have the same result.

If you create keys like this: map.put(new Key(x,y),V); you will never compare the references of your keys. Cause everytime you want to acces the map, you will do something like map.get(new Key(x,y));. Therefore your equals() does not need a statement like if (this == obj). It will never occure.

Instead of if (getClass() != obj.getClass()) in your equals() better use if (!(obj instanceof this)). It will be valid even for subclasses.

So the only thing you need to compare is actually X and Y. So the best equals() implementation in this case would be:

public boolean equals (final Object O) {
  if (!(O instanceof Key)) return false;
  if (((Key) O).X != X) return false;
  if (((Key) O).Y != Y) return false;
  return true;
}

So in the end your key class is like this:

public class Key {

  public final int X;
  public final int Y;

  public Key(final int X, final int Y) {
    this.X = X;
    this.Y = Y;
  }

  public boolean equals (final Object O) {
    if (!(O instanceof Key)) return false;
    if (((Key) O).X != X) return false;
    if (((Key) O).Y != Y) return false;
    return true;
  }

  public int hashCode() {
    return (X << 16) + Y;
  }

}

You can give your dimension indices X and Y a public access level, due to the fact they are final and do not contain sensitive information. I'm not a 100% sure whether private access level works correctly in any case when casting the Object to a Key.

If you wonder about the finals, I declare anything as final which value is set on instancing and never changes - and therefore is an object constant.


Implemented in common-collections MultiKeyMap


You can download it from the below link: https://github.com/VVS279/DoubleKeyHashMap/blob/master/src/com/virtualMark/doubleKeyHashMap/DoubleKeyHashMap.java

https://github.com/VVS279/DoubleKeyHashMap

You can use double key: value hashmap,

   DoubleKeyHashMap<Integer, Integer, String> doubleKeyHashMap1 = new 
   DoubleKeyHashMap<Integer, Integer, String>();

   DoubleKeyHashMap<String, String, String> doubleKeyHashMap2 = new 
   DoubleKeyHashMap<String, String, String>();

If they are two integers you can try a quick and dirty trick: Map<String, ?> using the key as i+"#"+j.

If the key i+"#"+j is the same as j+"#"+i try min(i,j)+"#"+max(i,j).


You can also use guava Table implementation for this.

Table represents a special map where two keys can be specified in combined fashion to refer to a single value. It is similar to creating a map of maps.

//create a table
  Table<String, String, String> employeeTable = HashBasedTable.create();

  //initialize the table with employee details
  employeeTable.put("IBM", "101","Mahesh");
  employeeTable.put("IBM", "102","Ramesh");
  employeeTable.put("IBM", "103","Suresh");

  employeeTable.put("Microsoft", "111","Sohan");
  employeeTable.put("Microsoft", "112","Mohan");
  employeeTable.put("Microsoft", "113","Rohan");

  employeeTable.put("TCS", "121","Ram");
  employeeTable.put("TCS", "122","Shyam");
  employeeTable.put("TCS", "123","Sunil");

  //get Map corresponding to IBM
  Map<String,String> ibmEmployees =  employeeTable.row("IBM");

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to hash

php mysqli_connect: authentication method unknown to the client [caching_sha2_password] What is Hash and Range Primary Key? How to create a laravel hashed password Hashing a file in Python PHP salt and hash SHA256 for login password Append key/value pair to hash with << in Ruby Are there any SHA-256 javascript implementations that are generally considered trustworthy? How do I generate a SALT in Java for Salted-Hash? What does hash do in python? Hashing with SHA1 Algorithm in C#

Examples related to hashmap

How to split a string in two and store it in a field Printing a java map Map<String, Object> - How? Hashmap with Streams in Java 8 Streams to collect value of Map How to convert String into Hashmap in java Convert object array to hash map, indexed by an attribute value of the Object HashMap - getting First Key value The type java.util.Map$Entry cannot be resolved. It is indirectly referenced from required .class files Sort Go map values by keys Print all key/value pairs in a Java ConcurrentHashMap creating Hashmap from a JSON String

Examples related to hashcode

Hashing with SHA1 Algorithm in C# HashMaps and Null values? How to create a HashMap with two keys (Key-Pair, Value)? What is hashCode used for? Is it unique? How does a Java HashMap handle different objects with the same hash code? Hashcode and Equals for Hashset What is the use of hashCode in Java? Good Hash Function for Strings Why do I need to override the equals and hashCode methods in Java? Memory address of variables in Java