У меня есть java объект, который имеет некоторые поля int / string / enum
public class Key{
String name;
int id;
Map<Integer, Type> valueMap; //type is an enum
public void write(final ByteBuffer byteBuffer) throws IOException {
byteBuffer.clear();
byte[] nameBytes= name.getBytes(Charset.forName("UTF-8"));
byteBuffer.putInt(nameBytes.length);
byteBuffer.put(nameBytes);
byteBuffer.putInt(id);
writeMap(valueMap, byteBuffer);
}
private void writeMap(Map<Integer, Type> map, ByteBuffer byteBuffer) throws IOException
{
byteBuffer.putInt(map.size());
for(Map.Entry<Integer, Type> e : map.entrySet()) {
byteBuffer.putInt(e.getKey().getId());
byteBuffer.putInt(e.getValue().getId());
}
}
public static Key read(final ByteBuffer byteBuffer) throws IOException {
int stringLen = byteBuffer.getInt();
byte[] nameBytes= new byte[stringLen];
byteBuffer.get(nameBytes);
String name= new String(name);
int id= byteBuffer.getInt();
Map<Integer, Type> valueMap= readMap(byteBuffer);
return new Key(name, id, map);
}
private static Map<Integer, Type> readMap(ByteBuffer byteBuffer) throws IOException
{
int r = byteBuffer.getInt();
if(r==-1) {
return ImmutableMap.of();
} else {
ImmutableMap.Builder<Integer, Type> mm = ImmutableMap.builder();
for(int i=0; i<r; i++) {
int k = byteBuffer.getInt();
Type v = Type.of(byteBuffer.getInt());
mm.put(k,v);
}
return mm.build();
}
}
.....//constructor and getter/setter present
}
CustomCodec:
public class CustomCodec implements RedisCodec<Key, Set<Long>> {
@Override
public Key decodeKey(ByteBuffer bytes) {
try {
bytes.flip();
return Key.read(bytes);
} catch (IOException e) {
return null;
}
}
@Override
public Set<Long> decodeValue(ByteBuffer bytes) {
bytes.flip();
int size = bytes.getInt();
Set<Long> values = new HashSet<Long>();
for(int i=0; i<size; i++){
values.add(bytes.getLong());
}
return values;
}
@Override
public ByteBuffer encodeKey(Key key) {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(100);
key.write(byteBuffer);
return byteBuffer;
}
} catch (IOException e) {
return null;
}
}
@Override
public ByteBuffer encodeValue(Set<Long> value) {
try {
ByteBuffer byteBuffer = ByteBuffer.allocate(value.size() * Long.BYTES + Integer.BYTES);
byteBuffer.clear();
byteBuffer.putInt(value.size());
value.stream().forEach(i -> byteBuffer.putLong(i));
byteBuffer.flip();
return byteBuffer;
} catch (IOException e) {
return null;
}
}
}
Использование этого приводит к BufferUnderFlowException в encodeValue (). Тем не менее, когда я пишу простой тест для подтверждения кодирования и декодирования, он работает нормально. Могу ли я знать, знает ли кто-нибудь, могут ли объекты java быть преобразованы непосредственно в Bytebuffer и могут ли они использоваться в качестве ключей redis с использованием салата?
Я пытался использовать ByteArrayOutputStream / ByteArrayInputStream, и он отлично работает с ним. Но я где-то читал, это должно быть быстрее, если использовать ByteBuffer напрямую.
Заранее большое спасибо!