Подтвердить что ты не робот

IdentityHashMap возвращает неверное значение

Насколько я понимаю, следующий код должен печатать false, поскольку он выполняет сравнение на основе identity.

Однако, когда я запускаю следующий код, он печатает true:

public class Test1 {
  public static void main(String[] args) {
    IdentityHashMap m = new IdentityHashMap();
    m.put("A", new String("B"));
    System.out.println(m.remove("A", new String("B")));
  }
}

Может кто-нибудь помочь мне понять это поведение?

4b9b3361

Ответ 1

Фактически вы нажмете ошибку в JDK, см. JDK-8178355. IdentityHashMap не имеет пользовательской реализации метода remove(K,V), добавленного в Map с помощью метода по умолчанию, что вызывает эту проблему.

Ответ 2

Вы положите "A", новый "B"

Вы удалите "A", новый "B"

Итак, да, ваше предположение, что этот IdentityHashMap должен не удалить это значение, выглядит правильно.

Но вы используете метод remove(key, value) из базы AbstractMap - который не переопределяется этим конкретным подклассом!

Итак, хотя javadoc говорит:

Этот класс реализует интерфейс Map с хэш-таблицей, используя ссылочное равенство вместо равенства объектов при сравнении ключей (и значений).

Часть (и значений) (возможно) реализована только для вставки пар ключ/значение.

Итак, важная часть снова исходит из javadoc:

Этот класс не является реализацией карты общего назначения! Хотя этот класс реализует интерфейс Map, он намеренно нарушает общий контракт Map, который предусматривает использование метода equals при сравнении объектов. Этот класс предназначен для использования только в редких случаях, когда требуется семантика ссылочного равенства.

Мой (вероятно, упрямый) отбор: этот класс - особенная вещь. Он имеет очень четкую и узкую цель. И вы нашли пример, где он разваливается. (что я не нахожу удивительным: когда вы "меняете" семантику, но решаете повторно использовать существующий код, почти неизбежно сталкиваться с такими несоответствиями).

Это можно рассматривать как ошибку; и, как подтверждает другой ответ: это bug!