我想在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);
现在,使用简单键的缓存中的元素较少,但是值更大且更复杂。在缓存中对成千上万个元素进行测试时,删除的速度很快,放置和获取的速度似乎没有明显降低。
这是有效的解决方案还是有更好的方法?
答案 0 :(得分:1)
我建议你使用computeIfAbsent
并保存put和get调用如下:
cache.computeIfAbsent(key.getId(), k -> new HashMap<Integer,Value>()).put(key.getInt(),value);
此方法确保仅在主映射中尚未映射时才创建辅助映射,并节省了额外的get调用,因为它返回了映射到主键的辅助映射。
参考文献: