0

I want to compare the elements of a map using HashCode. Is it possible to do so?

For example, my HashMap looks like this:

HashMap<Integer,String> map=new HashMap<Integer, String>();
map.put(123,"ABC");
map.put(345,"Abc");
map.put(245,"abc");

I assume that all the values must have same hash codes, so that I can compare them and get all keys(123,345,245).

Is my assumption correct? Can I use hash codes in order to compare the keys?

Nick Louloudakis
  • 5,856
  • 4
  • 41
  • 54

4 Answers4

1

You don't need to do that explicitly.

HashMap already hashes its keys.

Just invoke: map.keySet() to get the Set of your keys.

Example

HashMap<Integer,String> map = new HashMap<Integer, String>();
map.put(123,"ABC");
map.put(345,"Abc");
map.put(245,"abc");
System.out.println(map.keySet());

Output

[245, 123, 345]

What if I need the keys sorted (here, in their natural order)?

Two solutions.

  1. Use a TreeMap instead

    Map<Integer,String> map = new TreeMap<Integer, String>();

  2. Wrap the Set around a TreeSet later on

    System.out.println(new TreeSet<Integer>(map.keySet()));

Mena
  • 47,782
  • 11
  • 87
  • 106
  • Thank you for the answer. I actually want to make a phone directory sort of thing where if the name matches, it should be able to retrieve all the phone numbers matching to the name. – Sulava Mahapatra Jan 29 '15 at 16:51
  • @SulavaMahapatra I would suggest mapping the other way around : the name as key, and a set of phone numbers as value then. **Edit** do **not** use a numeric value for a phone number! Use a `String`. So you would have something like a `Map>`... – Mena Jan 29 '15 at 16:52
  • Ya okay that would be a correct approach. Thank you so much. – Sulava Mahapatra Jan 29 '15 at 16:56
1

It seems to me that what you really want is to make the name to be key of the map and the corresponding telephone number set the value.

Also you want that your keys are not case sensitive... String instances that differ in case will have different hash-codes and so you cannot use them here as the key per se. What you need to do then is to transform names into a canonical form, say all lowercase, when accessing the map so that difference in case is not relevant any longer.

There is a few way to go about this... extending a HashMap to suit your needs is an elegant one.

Better to use a String to store phone number as often they do contain non numeric characters...

public class PhoneBook extends HashMap<String,Set<String>> {

   public PhoneBook() { }

   public PhoneBook(int initialCapacity) { super(initialCapacity); }

   // Use this method to add numbers to the phone-book
   // returns true if the phone directory changed as a result of the call.
   public boolean add(String name, String number) {
        String canonicalName = name.toLowerCase();
        Set<String> existingNumbers = super.get(name);
        if (existingNumbers == null) 
            super.put(canonicalName,existingNumbers = new HashSet<>(10)); 
        // give an estimate capacity per name, in this example 10.           
        return existingNumbers.add(number);
   }  

   @Override
   public Set<String> put(String name, Set<String> numberSet) {
        throw new UnsupportedOperationException("you must use add(String) to add numbers");
   }

   @Override
   public Set<String> get(String name) {
       String canonicalName = name.toLowerCase();
       Set<String> existingNumbers = super.get(canonicalName);
       return existingNumbers == null ? Collections.EMPTY_SET : existingNumbers;
   }

} 

You may need to override some other operations from Map/Hash map to make sure consistency is preserved.

Valentin Ruano
  • 2,726
  • 19
  • 29
0

Your assumption is not correct.

From Wikipedia:

In the Java programming language, every class implicitly or explicitly provides a hashCode() method, which digests the data stored in an instance of the class into a single hash value (a 32-bit signed integer). This hash is used by other code when storing or manipulating the instance (...). This property is important to the performance of hash tables and other data structures that store objects in groups ("buckets") based on their computed hash values.

Now, each of your instance has a hash code that can be same or different with the hash code of other objects. The Map collection uses that hash code (via the hashcode() method) of your keys in order to store data in buckets internally (If you want more details on this, look here).

As aforementioned, this does not mean that all the objects stored in the same bucket have for sure the same or different hash code though.

UPDATE: Why do you want to compare the objects using their hash codes? If you want to compare the keys or the values of the map, I suggest that you make a value or object comparison by iterating the set of them (you can get them by map.keySet() or map.values() respectively) and not by using hash code. You can not be sure whether or not the value from hashCode() will be the same or different for different objects.

Community
  • 1
  • 1
Nick Louloudakis
  • 5,856
  • 4
  • 41
  • 54
  • Thanks for sharing the link. Does that mean I can compare two objects of different classes using the hashcode ? – Sulava Mahapatra Jan 29 '15 at 16:53
  • I updated the answer. Not necessarily. I suggest using other methods than hash codes, as you can not be sure whether or not they are the same or different. – Nick Louloudakis Jan 29 '15 at 17:09
0

There are different ways to achieve this i.e. single key -> multi values

  1. Using Hashmap and arraylist combine
  2. Using guava collections's multimap
  3. Using multimap provided by apache commons collection

Here is detail explanation: http://java.dzone.com/articles/hashmap-%E2%80%93-single-key-and

codinnvrends
  • 264
  • 2
  • 8