当在Xamarin中使用字节数组作为键时,ConcurrentHashMap无法按预期工作

时间:2018-04-24 18:57:16

标签: java xamarin xamarin.android concurrenthashmap

以下是我在Xamarin Android中使用的代码块。

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 :(得分:1)

使用字节数组作为Java映射的关键是一个非常糟糕的主意,原因有几个:数组是可变的,数组不具有引用相等性。这两件事都破坏了Map的总契约。我建议你为地图使用不同的键。有关更多信息,请参阅this question及其答案,包括将字节数组转换为可用的映射键的一些可能方法。

答案 1 :(得分:1)

只要你只希望你的密钥引用相等 - 数组就不能实现" 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 []使用equalshashCode的对象标识,所以 在HashMap中不匹配。

您可以使用给定的选项:

  1. 使用List<Byte>(内存可能很贵)。
  2. 执行自己的包装类,编写hashCodeequals以使用字节数组的内容。