编年史地图 - 值数据类型
chronicle map - value data types
在值方为地图或集合的情况下,实现编年史地图的最佳方式是什么?
我需要类似于以下的数据结构,我可以在其中存储具有特定 id 的某些数据的多个版本:
chronicle-map: String -> Map<String,V>
$id -> {v0-> value-v0, v1-> value-v1, v2 -> value-v2}
或者可能有两张地图:
chronicle-map-1: String -> Set<String>
key-$id -> Set{v0,v1,v2}
chronicle-map-2: String -> V
version-$id-v0 -> value-v0
version-$id-v1 -> value-v1
version-$id-v2 -> value-v2
(原子性和序列化性能是我主要关心的问题)。 acquireUsingLocked/getUsingLocked
方法似乎不适用于标准 map/set 实现。
- 你当然应该做的是切换到 Chronicle Map 3.x,因为这个版本定义了新的、可靠的模式和抽象集,它将发展以支持 "native"
Multimap
有时。
[以下问候编年地图3.x]
为了确保原子性(线程安全),您可以:
使用Java 8的新Map方法:compute()
、computeIfAbsent()
、computeIfPresent()
或merge()
方法,如:
static <K, V> void multiMapAdd(ChronicleMap<K, Set<V>> map, K key, V value) {
map.compute(key, (k, v) -> {
if (v == null)
v = new HashSet<>();
v.add(value);
return v;
});
}
获取上下文,并使用值字节进行操作,可能是为了优化一些 serialization/deserialization 成本。例如
interface LimitedSet {
public static final int MAX_VALUES_SIZE = 20;
byte getSize();
void setSize(byte);
MyValue getValue(int index);
void setValue(@MaxSize(MAX_VALUES_SIZE) int index, MyValue value);
}
...
try (ExternalMapQueryContext<K, LimitedSet, ?> cxt = map.queryContext(key) {
cxt.writeLock().lock();
MapEntry<K, LimitedSet> entry = cxt.entry();
if (entry == null) {
MapAbsentEntry<K, LimitedSet> absentEntry = cxt.absentEntry();
cxt.insert(absentEntry, absentEntry.defaultValue());
entry = cxt.entry();
assert entry != null;
}
LimitedSet values = entry.value().get();
int size = values.getSize();
for (int i = 0; i < size; i++) {
if (same(values.getValue(i), value))
return false;
}
if (size == MAX_VALUES_SIZE)
throw new IllegalStateException("values set overflow");
values.set(size, value);
values.setSize((byte) (size + 1));
}
您还可以在 Chronicle Map 自述文件中找到 Chronicle Map 的一些此类高级 "MultiMap" 用法,它揭示了 CRDT 复制和多条目锁定等其他功能:
在值方为地图或集合的情况下,实现编年史地图的最佳方式是什么?
我需要类似于以下的数据结构,我可以在其中存储具有特定 id 的某些数据的多个版本:
chronicle-map: String -> Map<String,V>
$id -> {v0-> value-v0, v1-> value-v1, v2 -> value-v2}
或者可能有两张地图:
chronicle-map-1: String -> Set<String>
key-$id -> Set{v0,v1,v2}
chronicle-map-2: String -> V
version-$id-v0 -> value-v0
version-$id-v1 -> value-v1
version-$id-v2 -> value-v2
(原子性和序列化性能是我主要关心的问题)。 acquireUsingLocked/getUsingLocked
方法似乎不适用于标准 map/set 实现。
- 你当然应该做的是切换到 Chronicle Map 3.x,因为这个版本定义了新的、可靠的模式和抽象集,它将发展以支持 "native"
Multimap
有时。
[以下问候编年地图3.x]
为了确保原子性(线程安全),您可以:
使用Java 8的新Map方法:
compute()
、computeIfAbsent()
、computeIfPresent()
或merge()
方法,如:static <K, V> void multiMapAdd(ChronicleMap<K, Set<V>> map, K key, V value) { map.compute(key, (k, v) -> { if (v == null) v = new HashSet<>(); v.add(value); return v; }); }
获取上下文,并使用值字节进行操作,可能是为了优化一些 serialization/deserialization 成本。例如
interface LimitedSet { public static final int MAX_VALUES_SIZE = 20; byte getSize(); void setSize(byte); MyValue getValue(int index); void setValue(@MaxSize(MAX_VALUES_SIZE) int index, MyValue value); } ... try (ExternalMapQueryContext<K, LimitedSet, ?> cxt = map.queryContext(key) { cxt.writeLock().lock(); MapEntry<K, LimitedSet> entry = cxt.entry(); if (entry == null) { MapAbsentEntry<K, LimitedSet> absentEntry = cxt.absentEntry(); cxt.insert(absentEntry, absentEntry.defaultValue()); entry = cxt.entry(); assert entry != null; } LimitedSet values = entry.value().get(); int size = values.getSize(); for (int i = 0; i < size; i++) { if (same(values.getValue(i), value)) return false; } if (size == MAX_VALUES_SIZE) throw new IllegalStateException("values set overflow"); values.set(size, value); values.setSize((byte) (size + 1)); }
您还可以在 Chronicle Map 自述文件中找到 Chronicle Map 的一些此类高级 "MultiMap" 用法,它揭示了 CRDT 复制和多条目锁定等其他功能: