我想在 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);
但是 put 需要 get:
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 调用。
引用文献:
关于java - 访问按键分组的缓存元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54459558/