我有带有键-> 值映射的咖啡因缓存。Key
接口的实现有多种不同的equals
方法。为了从基于 的缓存中删除值someOtherVal
,我不得不使用cache.asMap().keySet().removeIf(comp::isSame)
超级慢的代码。
对于这种缓存中单值映射的许多键,还有其他解决方案吗?我想到的一件事是有 2 个 Cache 实例,一个带有Cache<Key, String>
,另一个带有Cache<someOtherVal, Key>
,每当我想删除一个值时,我都会使用另一个缓存来定位 Key 。
那么唯一的问题是如何使这两个缓存保持同步?是否已经有解决方案?
import java.time.Duration;
import java.util.Objects;
import java.util.UUID;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.base.Stopwatch;
public class Removal {
private static final int MAX = 1_000_000;
interface Key{
String getSomeOtherVal();
default boolean isSame(Key k){
return Objects.equals(k.getSomeOtherVal(),getSomeOtherVal());
}
}
static class KeyImpl implements Key{
int id;
String someOtherVal;
public KeyImpl(int id, String someOtherVal) {
this.id = id;
this.someOtherVal = someOtherVal;
}
public int getId() {
return id;
}
@Override
public String getSomeOtherVal() {
return someOtherVal;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
KeyImpl key = (KeyImpl)o;
return id == key.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
Cache<Key, String> cache = Caffeine.newBuilder().build();
public static void main(String[] args) {
Removal s = new Removal();
s.fill();
Duration sRem = s.slowRemovalFirst100();
Duration fRem = s.fastRemoval100To200();
System.out.println("Slow removal in " + sRem);
System.out.println("Fast removal in " + fRem);
}
private Duration slowRemovalFirst100(){
Stopwatch sw = Stopwatch.createStarted();
for(int i=0; i<100; i++){
Key comp = new KeyImpl(i, String.valueOf(i));
cache.asMap().keySet().removeIf(comp::isSame); //Finds a key by some other property and then removes it (SLOW)
//System.out.println("Removed " + i);
}
return sw.stop().elapsed();
}
private Duration fastRemoval100To200(){
Stopwatch sw = Stopwatch.createStarted();
for(int i=100; i<200; i++){
Key comp = new KeyImpl(i, String.valueOf(i));
cache.invalidate(comp); //Uses direct access to map by key (FAST)
//System.out.println("Removed " + i);
}
return sw.stop().elapsed();
}
private void fill(){
for(int i=0; i<MAX; i++){
cache.put(new KeyImpl(i, String.valueOf(i)), UUID.randomUUID().toString());
}
}
}
在我的机器上运行此代码的结果:
Slow removal in PT2.807105177S
Fast removal in PT0.000126183S
哪里能看出这么大的区别……