Я использую этот код, чтобы проверить, что массив присутствует в HashMap
:
public class Test {
public static void main(String[] arg) {
HashMap<int[], String> map = new HashMap<int[], String>();
map.put(new int[]{1, 2}, "sun");
System.out.println(map.containsKey((new int[]{1, 2})));
}
}
Но это печатает False
. Как я могу проверить, что массив присутствует в HashMap
?
Проблема в том, что два int []
не равны.
System.out.println(
(new int[] { 1, 2 }).equals(new int[] { 1, 2 })
); // prints "false"
Карта
и другие классы Java Collections Framework определяют свой интерфейс в терминах равняется
. Из Map API
:
Многие методы в интерфейсах Collections Framework определены в терминах метода
равно
. Например, спецификация для методаcontainsKey (Object key)
говорит: «возвращаетtrue
тогда и только тогда, когда эта карта содержит отображение для ключаk
, например that(key == null? k == null: key.equals (k))
. "
Обратите внимание, что они не обязательно должны быть одним и тем же объектом; они просто должны быть равными
. Массивы в Java расширяются от Object
, реализация которого по умолчанию equals
возвращает истину только для идентичности объекта; поэтому он печатает false
в приведенном выше фрагменте.
Вы можете решить вашу проблему одним из многих способов:
равно
, использует java.util.Arrays
equals / deepEquals
метод.
@Override равно (Object)
, вы также должны @Override hashCode
Список
, который действительно определяет равно
с точки зрения содержащихся в них значений равно
, вы можете просто придерживаться того, что у вас есть. Точно так же, как вы не должны ожидать, что приведенный выше фрагмент кода когда-либо напечатает true
, вы никогда не должны ожидать, что сможете найти свои массивы только по его значениям; вы должны каждый раз цепляться за исходные ссылки и использовать их. Object.equals
и Object.hashCode
Реализация hashCode ()
для массивов получена из Object.hashCode ()
, поэтому она зависит от место в памяти массива. Поскольку два массива создаются отдельно, они имеют разные ячейки памяти и, следовательно, разные хэш-коды. Если вы сделаете один массив, он будет работать:
int[] arr = {1, 2};
map.put(arr, "sun");
System.out.println(map.containsKey(arr));
У вас есть два разных объекта, которые содержат одинаковые значения, потому что вы дважды вызывали new.
Один из подходов, который вы можете использовать, - это создать собственный класс-«держатель» и определить методы equals и hash этого класса.
Вы уверены, что не хотите отображать Строки
в массивы, а не наоборот?
В любом случае, чтобы ответьте на ваш вопрос, проблема в том, что вы создаете новый
массив при вызове containsKey ()
. Это возвращает false, если у вас есть два отдельно новых
ed массивов, которые имеют одинаковые элементы и размеры. См. Ответ Ювала, чтобы узнать, как правильно проверить, содержится ли массив в качестве ключа.
Альтернативный, более продвинутый подход - создать собственный класс, который обертывает массив и перезаписывает hashCode ()
, так что два массива с одинаковым размером и элементами будут иметь одинаковые хэш-коды.
Я думаю, что проблема в том, что ваш массив выполняет сравнение '==', т.е. проверяет ссылку. Когда вы делаете containsKey(new int[] { ... }), он создает новый объект, и поэтому ссылка не та же самая.
Если вы измените тип массива на что-то вроде ArrayList
, это должно сработать, однако я бы старался избегать использования списков в качестве ключей карты, поскольку это будет не очень эффективно.
Вы сравниваете две разные ссылки - обратите внимание на двойное использование new
.
Сработает что-то вроде этого:
public class Test {
public static void main(String[] arg)
{
HashMap<int[],String> map= new HashMap<int[],String>();
int[] a = new int[]{1,2};
map.put(a, "sun");
System.out.println(map.containsKey(a));
}
}
Поскольку a
является той же самой ссылкой, вы получите true
, как и ожидалось. Если в вашем приложении нет возможности передавать ссылки для сравнения, я бы создал новый тип объекта, содержащий int[]
и переопределил метод equals()
(не забудьте одновременно переопределить hashCode()
), чтобы это отразилось в вызове containsKey()
.
Я бы использовал другой подход. Как упоминалось ранее, проблема заключается в равенстве массивов, которое основано на равенстве ссылок и делает вашу карту бесполезной для ваших нужд. Другой потенциальной проблемой, предполагающей, что вы используете вместо этого ArrayList, является проблема согласованности: если вы измените список после того, как он был добавлен на карту, у вас будет повреждение хэш-карты, поскольку позиция списка не будет отражать его хэш-код больше.
Чтобы решить эти две проблемы, я бы использовал какой-то неизменяемый список. Вы можете создать неизменяемую оболочку, например, для массива int и самостоятельно реализовать equals () и hashCode ().