ConcurrentHashMap не работает должным образом при использовании байтового массива в качестве ключа в Xamarin - PullRequest
0 голосов
/ 24 апреля 2018

Вот кодовый блок, который я использую в Android Xamarin.

Java.Util.Concurrent.ConcurrentHashMap map = new Java.Util.Concurrent.ConcurrentHashMap();
var key = new byte[] { 1, 2, 3 };
var data = new byte[] { 1, 2, 3, 4, 5 };

map.Put(key, data);
var val = map.Get(key); // null, WHY?

IEnumeration keys = map.Keys();
while (keys.HasMoreElements)
{
    var k = keys.NextElement();
    var val2 = map.Get(k); // NOT null, val2 is byte array of {1,2,3,4,5}
}

Я ожидал, val - это байтовый массив (данные), но val - ноль, а val2 - не ноль.

Но этот Java-код работает очень хорошо.

java.util.concurrent.ConcurrentHashMap map = new java.util.concurrent.ConcurrentHashMap();

byte[] key = {1, 2, 3};
byte[] data = {1, 2, 3, 4, 5};

map.put(key, data);
Object o = map.get(key); // byte array of {1,2,3,4,5}

В чем причина?

Ответы [ 2 ]

0 голосов
/ 24 апреля 2018

Пока вам нужно только равенство ссылок для вашего ключа - массивы не реализуют "value equality" так, как вы, вероятно, хотели бы, но List делает. Например:

   byte[] key = new byte[] { 1, 2, 3 };
            byte[] data = new byte[] { 1, 2, 3 };
            System.out.println(key.equals(data));
            System.out.println(key.hashCode());
            System.out.println(data.hashCode());

Это даст вывод:

false
1829164700
2018699554

Пример 2 ::

int[] key = new int[] { 1, 2, 3 };
        int[] data = new int[] { 1, 2, 3 };
        List<Integer> list1 = Arrays.asList(1, 2);
        List<Integer> list2 = Arrays.asList(1, 2);

        System.out.println("Comparison between LIST ::" + list1.equals(list2));
        System.out.println("Comparison between arrays ::" + key.equals(data));
        System.out.println(key.hashCode());
        System.out.println(data.hashCode());

Вывод: *

Comparison between LIST ::true
Comparison between arrays ::false
1829164700
2018699554

Проблема в том, что byte [] использует идентификатор объекта для equals и hashCode, так что не будет совпадать в HashMap.

Вы можете использовать данные опции:

  1. Используйте List<Byte> (может быть дорого в памяти).
  2. Создайте свой собственный класс переноса, написав hashCode и equals, чтобы использовать содержимое массива байтов.
0 голосов
/ 24 апреля 2018

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

...