#java #hashmap
#java #hashmap
Вопрос:
Как это возможно: HashMap<byte[], byte[]>
и что такое hash() байта[] ?
Комментарии:
1. Что в этом такого странного? Массивы являются объектами, поэтому это разрешено.
2.
System.out.println(new byte[10].hashCode());
дает мне209777867
.
Ответ №1:
Да, это возможно (с большой оговоркой, см. Ниже), но byte[]
не является «внутренним типом». Во-первых, такого понятия не существует, вы, вероятно, имеете в виду «примитивный тип». Во-вторых: byte[]
это не примитивный тип, byte
есть. Массив всегда является ссылочным типом.
Массивы не имеют конкретных hashCode
реализаций, поэтому они будут просто использовать hashCode
of Object
, что означает, что hashCode
будет indentity- hashCode
, который не зависит от фактического содержимого.
Другими словами: a byte[]
— очень плохой Map
ключ, потому что вы можете получить значение только с точно таким же экземпляром.
Если вам нужен контент hashCode()
на основе массива, вы можете использовать Arrays.hashCode()
, но это не поможет вам (напрямую) с Map
. Также Arrays.equals()
необходимо проверить равенство содержимого.
Вы могли бы обернуть свой byte[]
объект в тонкую оболочку, которая реализует hashCode()
и equals()
(используя методы, упомянутые выше):
import java.util.Arrays;
public final class ArrayWrapper {
private final byte[] data;
private final int hash;
public ArrayWrapper(final byte[] data) {
// strictly speaking we should make a defensive copy here,
// but I *assume* (and should document) that the argument
// passed in here should not be changed
this.data = data;
this.hash = Arrays.hashCode(data);
}
@Override
public int hashCode() {
return hash
}
@Override
public boolean equals(Object o) {
if (!(o instanceof ArrayWrapper)) {
return false;
}
ArrayWrapper other = (ArrayWrapper) o;
return this.hash == other.hash amp;amp; Arrays.equals(this.data, other.data);
}
// don't add getData to prevent having to do a defensive copy of data
}
Используя этот класс, вы можете затем использовать a Map<ArrayWrapper,byte[]>
.
Комментарии:
1. Массив, вероятно, можно использовать с TreeMap, если вы реализуете свой пользовательский компаратор.
2.@AlexR: это могло бы сработать, но обратите внимание, что такой
TreeMap
интерфейс не будет корректно реализовыватьMap
интерфейс, поскольку для этого требуетсяComparator
, чтобы он соответствовалequals()
(т. Е.compare(a,b)
возвращал возврат0
iffa.equals(b)
).
Ответ №2:
Для массивов hashCode()
используется реализация по умолчанию из Object
— обычно некоторая форма адреса внутреннего объекта. В результате ключ в этом HashMap
считается уникальным, если это другой массив, а не если содержимое массива равно.
byte[] a = { 2, 3 };
byte[] b = { 2, 3 };
System.out.println(a.equals(b)); // false
Map<byte[], String> map = new HashMap<byte[], String>();
map.put(a, "A");
map.put(b, "B");
System.out.println(map); // {[B@37d2068d=B, [B@7ecec0c5=A}