Search code examples
javalistcomparatorcomparable

How to use indexOf on a List containing HashMap with multiple key/value pairs


I have a List containing HashMaps. Each HashMap in the list might have multiple key/value pairs. I want to indexOf on the list to find out the index of the element where the passed in HashMap is. However, the problem is that equals method of HashMap looks at all the entire entrySet while comparing. Which is not what I want.

Example:

    List<HashMap> benefit = new ArrayList<HashMap>();
    HashMap map1 = new HashMap();
    map1.put("number", "1");
    benefit.add(map1);
    HashMap map2 = new HashMap();
    map2.put("number", "2");
    map2.put("somethingelse", "blahblah"); //1
    benefit.add(map2);

    HashMap find = new HashMap();
    find.put("number", "2");
    int index = benefit.indexOf(find);
    if (index >= 0)
        System.out.println(benefit.get(index).get("number"));

The above code does not print anything because of line with //1.

  • What do I have to do so that the above code actually prints 2?
  • Is there a way to implement comparable on the list so that I can define my own?

Solution

  • I think you're looking for retainAll(), so you can compare only the elements you're interested in:

    int index = myIndexOf(benefit, find);
    
    ...
    
    static int myIndexOf(List<HashMap> benefit, Map find) {
        int i = 0;
        for (Map map : benefit) {
            Map tmp = new HashMap(map);
            tmp.keySet().retainAll(find.keySet());
            if (tmp.equals(find)) {
                return i;
            }
            i++;
        }
        return -1;
    }
    

    It's possible, of course, to declare your own subclass of List that overrides the indexOf method with this behaviour. However, I don't think that's a good idea. It would violate the contract of the indexOf method:

    returns the lowest index i such that (o==null ? get(i)==null : o.equals(get(i)))

    This would be confusing to someone else maintaining the code. You might then think that you could subclass HashMap to redefine equals, but that would violate the symmetry property of Object.equals().