Равенство между 2 HashMap - PullRequest
       60

Равенство между 2 HashMap

22 голосов
/ 03 ноября 2010

В методе equals () моего класса я использую частную переменную HashMap для сравнения на равенство.Тем не менее, 2 разных объекта по-прежнему показывают равные при сравнении их переменных HashMap.Дальнейшие исследования привели меня к ссылке: Ссылка здесь .Однако это просто говорит о том, что причина того, что HashMap1.equals (HashMap2) не работает, заключается в том, что «очевидно, массивы Java не могут быть проверены на равенство без написания специального кода».

Я не понял этой причины.Кто-нибудь может подсказать мне причину?

Ответы [ 4 ]

31 голосов
/ 03 ноября 2010

Метод equals для типа массива Java эквивалентен ==, поскольку "классы" массива Java не переопределяют Object.equals.

Если вы хотите сравнивать массивы «по значению», вам нужно либо использовать соответствующий метод java.util.Arrays.equals(...), либо реализовать его самостоятельно.

Если ваш HashHap использует массивы в качестве ключей или значений, то он вызовет метод массива equals, чтобы проверить, совпадают ли ключи и / или значения между двумя картами. Это заставит HashMap.equals вести себя странно (с вашей точки зрения). Вот что говорит связанная статья. Однако семантический массив только влияет на равенство HashMap, если вы используете массивы в качестве классов ключей или значений. Если вы этого не сделаете, то HashMap::equals должен просто работать как положено.

Javadocs для равенства в Map классах немного вовлечены, но они в основном сводятся к тому, чтобы взять два набора записей, сравнить их размеры, а затем выполнить s1.containsAll(s2). Конечно, это дорого, но должно работать для всех классов Map, которые правильно реализуют интерфейс Map.


Обратите внимание, что использование массивов в качестве ключей для карт является плохой идеей по нескольким причинам:

  1. Семантика массива equals и hashCode неверна для HashMap в большинстве сценариев. В большинстве случаев вам нужна карта для сравнения ключей по значению, а не по идентификатору объекта.
  2. Массивы изменчивы. Если мы предположили, что для решения проблемы equals / hashcode был найден обходной путь, вы могли бы все же сломать инварианты карты, изменив ключ массива.
10 голосов
/ 03 ноября 2010

Статья правильная. Хеш-карты можно безопасно сравнивать с помощью метода equals (), если можно сравнивать ключевые объекты и объекты-значения одним и тем же методом. В статье значения карты являются массивами, которые не реализуют equals (), как ожидалось. Вместо этого использование ArrayList решило бы проблему.

4 голосов
/ 03 ноября 2010

Собственные массивы Java не имеют функции .equals ().Поэтому, если значения вашего hashmap (или ключи, я полагаю) являются массивами, HashMap.equals () завершится ошибкой.Я подозреваю, что он прибегнет к Object.equals (), который просто проверяет, являются ли два объекта на самом деле одним и тем же объектом.чем массив [], поскольку контейнеры имеют свой собственный .equals (), который вызывает equals () для последовательных элементов контейнеров, а не просто проверяет, являются ли они одной и той же ссылкой.Код для реализации Collection.equals может выглядеть примерно так:

public boolean equals(Object o) {
  // sets never equal lists and visa versa
  if (o instanceof MyCollectionSubclass) {
    Iterator myIterator = iterator();
    Iterator theirIterator = ((Collection)o).iterator();
    while (myIterator.hasNext() && theirIterator.hasNext()) {
      Object myObj = myIterator.next();
      Object theirObj = theirIterator.next();
      if (!myObj.equals(theirObj)) {
        return false;
      }
    }
    // at least one will be false or we wouldn't have left the above while loop
    return myIterator.hasNext() == theirIterator.hasNext();
  }
  // not our class
  return false;
}

Это может привести к сравнению истинного значения в зависимости от того, что делает содержимое коллекции, когда вы вызываете их equals().

2 голосов
/ 03 ноября 2010

Массивы Java нельзя проверить на равенство без написания настраиваемого кода

Это просто сложный способ сказать, что массивы Java не переопределяют Object.equals().Следовательно, если вы сравните их, используя equals() (что и делают методы equals всех классов коллекции), вы получите «равенство экземпляров», а не «равенство значений».

Это действительно простоОсобый случай различных способов equals работает в зависимости от того, был ли он переопределен или нет.

...