简体   繁体   中英

ConcurrentHashMap doesn't work as expected when use byte array as key in Xamarin

Here is code block I use in 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}
}

I expected val is byte array (data), but val is null, while val2 is not null.

But this Java code works very well.

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}

What is the reason?

Using a byte array as a key to a Java map is a really bad idea for a few reasons: arrays are mutable, and arrays don't have reference equality. Both of these things break the general contract of Map. I suggest that you use a different key for the map. See this question and its answers for more information, including some possible ways to convert a byte array into a map key that will work.

So long as you only want reference equality for your key - arrays don't implement " value equality " in the way that you'd probably want, But List does. For example:

   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());

This will give a output :

false
1829164700
2018699554

Example 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());

The output is ::

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

The problem is that byte[] uses object identity for equals and hashCode , so that will not match in a HashMap.

You can use the given options :

  1. Use List<Byte> (can be expensive in memory).
  2. Do your own wrapping class, writing hashCode and equals to use the contents of the byte array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM