我想在JCS或Infinispan等缓存中使用复合键(String,int)缓存大量Java对象(String,byte [])。
密钥可以按字符串部分(让我们称之为ID)分组:
KEY = VALUE
-------------
A 1 = valueA1
A 4 = valueA4
A 5 = valueA5
B 9 = valueB9
C 3 = valueC3
C 7 = valueC7
我需要删除按键的ID部分分组的元素,例如A应该删除A 1,A 4和A 5。
首先,我试过这样的事情:
final List<String> keys = cache.keySet()
.stream().filter(k -> k.getId().equals(id)).collect(Collectors.toList());
keys.forEach(cache::remove);
虽然这是有效的,但这并不奇怪 - 非常昂贵且因此很慢。
所以我尝试了另一种方法,只使用ID作为键,并将值分组到地图中:
KEY = VALUE
---------------------------------------------
A = {1 = valueA1, 4 = valueA4, 5 = valueA5}
B = {9 = valueB9}
C = {3 = valueC3, 7 = valueC7}
删除组非常有效:
cache.remove(id);
但是推杆需要得到:
Map<Integer, Value> map = cache.get(key.getId());
if (map == null) {
map = new HashMap<>();
}
map.put(key.getInt(), value);
cache.put(key.getId(), map);
现在缓存中的元素越少,键越简单,但值越大越复杂。使用缓存中的数十万个元素进行测试,删除速度很快,而且放置和获取似乎没有明显变慢。
这是一个有效的解决方案还是有更好的方法?
我建议你使用computeIfAbsent
并保存一个put和get调用,如下所示:
cache.computeIfAbsent(key.getId(), k -> new HashMap<Integer,Value>()).put(key.getInt(),value);
仅当辅助映射尚未映射到主映射中时,此方法才能确保创建辅助映射,并且由于它返回映射到主键的辅助映射,因此无需额外的get调用。
参考文献: