Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check equality of LinkedHashMaps in Java - also taking the insertion-order into account?

I'd like to check the equality of two LinkedHashMaps in Java.

the equals()-method is located in AbstractMap and only checks if and entry with the same key and value is present in the compared list. Thus, the insertion order is not checked:

package com.stackoverflow.tests;

import java.util.LinkedHashMap;

public class LinkedHashMapEqualsTest {

  public static void main(String[] args) {
    LinkedHashMap<String, String> lhm1 = new LinkedHashMap<String, String>();
    lhm1.put("A", "1");
    lhm1.put("B", "2");
    lhm1.put("C", "3");
    LinkedHashMap<String, String> lhm2 = new LinkedHashMap<String, String>();
    lhm2.put("A", "1");
    lhm2.put("B", "2");
    lhm2.put("C", "3");
    LinkedHashMap<String, String> lhm3 = new LinkedHashMap<String, String>();
    lhm3.put("A", "1");
    lhm3.put("C", "3");
    lhm3.put("B", "2");
    LinkedHashMap<String, String> lhm4 = new LinkedHashMap<String, String>();
    lhm4.put("A", "1");
    lhm4.put("B", "2");
    LinkedHashMap<String, String> lhm5 = new LinkedHashMap<String, String>();
    lhm5.put("A", "2");
    lhm5.put("B", "2");
    lhm5.put("C", "3");

    if(lhm1.equals(lhm1)) {
      System.out.println("Positive control. - SUCCESS");
    }
    if(lhm1.equals(lhm2)) {
      System.out.println("lhm1 does equal lhm2; as expected. - SUCCESS");
    }
    if(lhm1.equals(lhm3)) {
      System.out.println("lhm1 does equal lhm3, although the insert-order is different.");
    }
    if(!lhm1.equals(lhm4)) {
      System.out.println("Negative control 1. - SUCCESS");
    }
    if(!lhm1.equals(lhm5)) {
      System.out.println("Negative control 2. - SUCCESS");
    }

  }

}

How can I check if also the insertion order is the same for both compared lists?

like image 854
Edward Avatar asked Apr 29 '16 14:04

Edward


People also ask

Does LinkedHashMap maintain insertion order in Java?

This class extends HashMap and maintains a linked list of the entries in the map, in the order in which they were inserted. This allows insertion-order iteration over the map. That is, when iterating a LinkedHashMap, the elements will be returned in the order in which they were inserted.

Does LinkedHashMap follow insertion order?

LinkedHashMap maintains the insertion order.

Does LinkedHashMap allow duplicates?

A LinkedHashMap cannot contain duplicate keys. LinkedHashMap can have null values and the null key. Unlike HashMap, the iteration order of the elements in a LinkedHashMap is predictable.

Does map maintain insertion order in Java?

P.S HashMap does not guarantee insertion order.


1 Answers

I'd probably not override equals() of LinkedHashMap but provide a helper method, e.g. like this (inspired by AbstractList#equals(...)):

public static <K, V> boolean linkedEquals( LinkedHashMap<K, V> left, LinkedHashMap<K, V> right) {
  Iterator<Entry<K, V>> leftItr = left.entrySet().iterator();
  Iterator<Entry<K, V>> rightItr = right.entrySet().iterator();

  while ( leftItr.hasNext() && rightItr.hasNext()) {
     Entry<K, V> leftEntry = leftItr.next();
     Entry<K, V> rightEntry = rightItr.next();

     //AbstractList does null checks here but for maps we can assume you never get null entries
     if (! leftEntry.equals(rightEntry))
         return false;
  }
  return !(leftItr.hasNext() || rightItr.hasNext());
} 

Then you use it like if( linkedEquals(lhm1, lhm3) ).

Edit:

As per request, another way which yields lower performance (due to multiple unnecessary iterations) but requires to write less code would be to convert the entry sets to lists and compare those, e.g. like this:

if( new ArrayList<>(lhm1.entrySet()).equals(new ArrayList<>(lhm3.entrySet()) ) { ... }
like image 160
Thomas Avatar answered Sep 30 '22 06:09

Thomas