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

Created on 24 Apr 2018  路  3Comments  路  Source: xamarin/xamarin-android

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

I expected valis byte array (data), but valis null, while val2is 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?

Most helpful comment

Addendum: if you use a Java.Lang.Object intermediary, it will work as you intend:

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

map.Put(key, data);
var val = map.Get(key); // val won't be null

val will, however, be a Java.Lang.Object. To get a byte[] back out, use the (byte[]) cast operator:

byte[] valData = (byte[]) val;

All 3 comments

What is the reason?

Same reason as here: arrays are deep marshaled on every call, resulting in a new/unique array instance on every method call.

Out of curiosity, why are you using Java.Util.Concurrent.ConcurrentHashMap and not ConcurrentDictionary<byte[], byte[]>?

Addendum: if you use a Java.Lang.Object intermediary, it will work as you intend:

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

map.Put(key, data);
var val = map.Get(key); // val won't be null

val will, however, be a Java.Lang.Object. To get a byte[] back out, use the (byte[]) cast operator:

byte[] valData = (byte[]) val;

It works great!
Thanks so much, @jonpryor

Was this page helpful?
0 / 5 - 0 ratings