SerializerArray<T>.deserialize() return Object[] instead of T[].

112 views
Skip to first unread message

Arulmurugan Subramaniam

unread,
Jun 20, 2016, 4:07:24 PM6/20/16
to MapDB

I have BTreeMap<String, Data[]> map = ..... If I call map.get("key"), It throws ClassCastException

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LMmTest$Data;
at com.c1x.rtb.test.MmTest.display(MmTest.java:59)
at com.c1x.rtb.test.MmTest.main(MmTest.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

Source:


import org.jetbrains.annotations.NotNull;
import org.mapdb.*;
import org.mapdb.serializer.SerializerArray;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.UUID;


public class MmTest {

static DB db = DBMaker.fileDB(new File("/tmp/fc/map3/db")).fileMmapEnableIfSupported().fileMmapPreclearDisable().closeOnJvmShutdown().make();

static BTreeMap<String, Data[]> map = db.treeMap("fc")
.keySerializer(Serializer.STRING)
.valueSerializer(new SerializerArray<Data>(new Serializer<Data>() {
@Override
public void serialize(@NotNull DataOutput2 out, @NotNull Data value) throws IOException {
out.write(ByteBuffer.allocate(4).putShort(value.value1).putShort(value.value2).array());
}

@Override
public Data deserialize(@NotNull DataInput2 input, int available) throws IOException {
return new Data(input.readShort(), input.readShort());
}

@Override
public int compare(Data first, Data second) {
return first.compareTo(second);
}
})).valuesOutsideNodesEnable().createOrOpen();

public static void main(String[] args) {
write();
display();
}

private static void write() {
String key = null;
for (long i = 0; i < 10; i++) {
key = UUID.randomUUID().toString().replace("-", "");
Data[] value = new Data[2];
value[0] = new Data((short) i, (short) i);
value[1] = new Data((short) i, (short) i);
map.put(key, value);
}
db.commit();
System.out.println(key);
}

private static void display() {
long count = 0;
for (Object object : map.keySet()) {
long start = System.currentTimeMillis();
Data[] data = map.<Data[]>get(object);
long end = System.currentTimeMillis();
System.out.println(++count + " " + object + " " + data[0] + " " + data[1] + " " + " took " + (end - start) + "ms.");
}
}


static class Data implements Comparable<Data>, Serializable {
Short value1;
Short value2;

public Data(Short value1, Short value2) {
this.value1 = value1;
this.value2 = value2;
}

@Override
public int compareTo(Data that) {
return this.value1.compareTo(that.value1);
}

@Override
public String toString() {
return "Data{" +
"value1=" + value1 +
", value2=" + value2 +
'}';
}
}
}

Jochen Wiedmann

unread,
Jun 21, 2016, 2:58:36 AM6/21/16
to ma...@googlegroups.com
On Mon, Jun 20, 2016 at 10:07 PM, Arulmurugan Subramaniam
<ar...@c1exchange.com> wrote:
>
> I have BTreeMap<String, Data[]> map = ..... If I call map.get("key"), It

Change the definition to BTreeMap<String, Object[]> and use casts,
where necessary. (Sorry, but Java serialization has its limits.)

Jochen



--
The next time you hear: "Don't reinvent the wheel!"

http://www.keystonedevelopment.co.uk/wp-content/uploads/2014/10/evolution-of-the-wheel-300x85.jpg

Arulmurugan Subramaniam

unread,
Jun 21, 2016, 4:11:39 AM6/21/16
to ma...@googlegroups.com
Thanks Jochen,

I have extended SerializerArray as below to server my purpose as I always to only one type of data.

Thanks,
Arulmurugan.S

import org.mapdb.DataInput2;
import org.mapdb.Serializer;
import org.mapdb.serializer.SerializerArray;

import java.io.IOException;

/**
* Created by arulmurugan on 6/21/16.
*/
public class MyArraySerializer<T> extends SerializerArray<MapDb3Test.Data> {


public MyArraySerializer(Serializer<MapDb3Test.Data> serializer) {
super(serializer);
}

@Override
public MapDb3Test.Data[] deserialize(DataInput2 in, int available) throws IOException {
MapDb3Test.Data[] ret = new MapDb3Test.Data[in.unpackInt()];
for (int i = 0; i < ret.length; i++) {
ret[i] = serializer.deserialize(in, -1);
}
return ret;
}
}


--
You received this message because you are subscribed to a topic in the Google Groups "MapDB" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mapdb/xVxBVCdsF3w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mapdb+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Jan Kotek

unread,
Jun 21, 2016, 4:17:50 AM6/21/16
to ma...@googlegroups.com
I will fix it today. ArraySerializer will get array class as optional parameter.
--
You received this message because you are subscribed to the Google Groups "MapDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mapdb+un...@googlegroups.com.

Jan Kotek

unread,
Jun 21, 2016, 9:47:40 AM6/21/16
to ma...@googlegroups.com
It is now fixed in master branch, updating snapshot repository. 

Will be in RC3 or stable release

Generics are discarted at runtime, so the SerializerArray has no way to know what type of array to return. 
Now it takes extra parameter which specifies array component type. The cast will work fine.

Jan

Arulmurugan Subramaniam

unread,
Jun 21, 2016, 9:48:59 AM6/21/16
to ma...@googlegroups.com
Thanks Jan

--
You received this message because you are subscribed to a topic in the Google Groups "MapDB" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/mapdb/xVxBVCdsF3w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to mapdb+un...@googlegroups.com.

Eduard Dudar

unread,
Nov 17, 2016, 12:41:14 AM11/17/16
to MapDB
Does not seem to work in 3.0.2 ...

BTreeMap<String, String[]> test =
        DBMaker.memoryDB().make()
                .treeMap("test", Serializer.STRING, new SerializerArray<>(Serializer.STRING))
                .createOrOpen();

test.put("t1", new String[] {"v11, v12"});
String[] v1 = test.get("t1");

compiles just fine but fails in runtime with 

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;



On Tuesday, June 21,
Reply all
Reply to author
Forward
0 new messages