java - Java Map with TimeToLive 与每个键/值对相关联
问题描述
最近我被要求(在一次采访中)设计HashMap
与每个键关联的 TTL。我使用下面给出的类似方法完成了它,但在他看来,这不是一个好方法,因为这需要在整个地图上进行迭代,如果地图大小以百万为单位,那么这将是一个瓶颈。
有没有更好的方法来做同样的事情?此外,他只关心一个线程在后台继续运行,尽管下一个 TTL 是几小时后。
class CleanerThread extends Thread {
@Override
public void run() {
System.out.println("Initiating Cleaner Thread..");
while (true) {
cleanMap();
try {
Thread.sleep(expiryInMillis / 2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void cleanMap() {
long currentTime = new Date().getTime();
for (K key : timeMap.keySet()) {
if (currentTime > (timeMap.get(key) + expiryInMillis)) {
V value = remove(key);
timeMap.remove(key);
System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);
}
}
}
}
解决方案
最好使用 aLinkedHashMap
以便您可以保留插入顺序。事实上LinkedHashMap
从HashMap
. 如果运行线程是问题所在,那么您可以通过扩展LinkedHashMap
. 在类内部,重写get
方法。
编辑:基于 onkar 的评论。最好覆盖get
而不是,put
因为这会阻止检索过期项目。
public class MyLinkedHashMap<K> extends LinkedHashMap<K, Date> {
private static final long expiryTime = 100000L;
private long currentOldest = 0L;
@Override
public Date get(Object key) {
long currentTime = new Date().getTime();
if ((currentOldest > 0L) && (currentOldest + expiryTime) < currentTime) {
// even the oldest key has not expired.
return super.get(key);
}
Iterator<Map.Entry<K, Date>> iter = this.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<K, Date> entry = iter.next();
long entryTime = entry.getValue().getTime();
if (currentTime >= entryTime + expiryTime) {
iter.remove();
} else {
// since this is a linked hash map, order is preserved.
// All the elements after the current entry came later.
// So no need to check the remaining elements if the current is not expired.
currentOldest = entryTime;
break;
}
}
return super.get(key);
}
}
推荐阅读
- vuejs2 - vuex get方法如何调用action方法?
- google-cloud-platform - 使用 DF 中嵌入的会话和侧板窗口更新数据流流作业
- python - 删除超出图像边缘的边界框
- node.js - 在用户名包含空格的 Windows 中,nvm 使用失败
- java - 在 Spring Boot 2.3 上注释 @MockBean 不起作用(未注入?)
- html - IE11 Flex 容器在表内时溢出
- javascript - 如何在本机反应中创建 Dragabble 列表?
- jenkins - 在 Jenkins Pipeline 视图中对并行阶段进行分组
- javascript - 如何清理 useffect 调用中的函数?
- python - setup.py 在分类器中包含许可证,但安装的轮子有 license=UNKNOWN