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

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

equals()The method is in AbstractMapand only checks if the same key and value are in the comparison 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 the insertion order is the same for both comparison lists?

+4
source share
2 answers

I would probably not override equals()of LinkedHashMap, but provide a helper method, for example. (inspired 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:

, (- ), , , , . :

if( new ArrayList<>(lhm1.entrySet()).equals(new ArrayList<>(lhm3.entrySet()) ) { ... }
+5

- - toString():

public static <K,V> boolean equalConsideringInsertionOrder(
  Map<K,V> left, Map<K,V> right){

  return left.toString().equals(right.toString());
}

, , . toString() , .

, :

public static <K, V> boolean equalConsideringInsertionOrder(
        Map<K, V> left, Map<K, V> right) {

    Iterator<Map.Entry<K, V>> leftIterator = left.entrySet().iterator();
    Iterator<Map.Entry<K, V>> rightIterator = right.entrySet().iterator();
    while (leftIterator.hasNext() && rightIterator.hasNext()) {
        Map.Entry<K, V> leftEntry = leftIterator.next();
        Map.Entry<K, V> rightEntry = rightIterator.next();
        if (!Objects.equals(leftEntry.getKey(), rightEntry.getKey())
                || !Objects.equals(leftEntry.getValue(),rightEntry.getValue())) {
            return false;
        }
    }
    return !leftIterator.hasNext() && !rightIterator.hasNext();
}
+1

All Articles