fix listener bug

This commit is contained in:
Looly 2022-10-12 00:05:31 +08:00
parent 7b7240aa4b
commit 9eb29695bf
3 changed files with 49 additions and 6 deletions

View File

@ -1,5 +1,6 @@
package cn.hutool.core.cache.impl; package cn.hutool.core.cache.impl;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.map.FixedLinkedHashMap; import cn.hutool.core.map.FixedLinkedHashMap;
import java.util.Iterator; import java.util.Iterator;
@ -42,7 +43,13 @@ public class LRUCache<K, V> extends ReentrantCache<K, V> {
this.timeout = timeout; this.timeout = timeout;
//链表key按照访问顺序排序调用get方法后会将这次访问的元素移至头部 //链表key按照访问顺序排序调用get方法后会将这次访问的元素移至头部
cacheMap = new FixedLinkedHashMap<>(capacity); final FixedLinkedHashMap<Mutable<K>, CacheObj<K, V>> fixedLinkedHashMap = new FixedLinkedHashMap<>(capacity);
fixedLinkedHashMap.setRemoveListener(entry -> {
if(null != listener){
listener.onRemove(entry.getKey().get(), entry.getValue().getValue());
}
});
cacheMap = fixedLinkedHashMap;
} }
// ---------------------------------------------------------------- prune // ---------------------------------------------------------------- prune

View File

@ -1,21 +1,28 @@
package cn.hutool.core.map; package cn.hutool.core.map;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
/** /**
* 固定大小的{@link LinkedHashMap} 实现<br> * 固定大小的{@link LinkedHashMap} 实现<br>
* 注意此类非线程安全由于{@link #get(Object)}操作会修改链表的顺序结构因此也不可以使用读写锁 * 注意此类非线程安全由于{@link #get(Object)}操作会修改链表的顺序结构因此也不可以使用读写锁
* *
* @author looly
*
* @param <K> 键类型 * @param <K> 键类型
* @param <V> 值类型 * @param <V> 值类型
* @author looly
*/ */
public class FixedLinkedHashMap<K, V> extends LinkedHashMap<K, V> { public class FixedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
private static final long serialVersionUID = -629171177321416095L; private static final long serialVersionUID = -629171177321416095L;
/** 容量,超过此容量自动删除末尾元素 */ /**
* 容量超过此容量自动删除末尾元素
*/
private int capacity; private int capacity;
/**
* 移除监听
*/
private Consumer<java.util.Map.Entry<K, V>> removeListener;
/** /**
* 构造 * 构造
@ -45,10 +52,25 @@ public class FixedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
this.capacity = capacity; this.capacity = capacity;
} }
/**
* 设置自定义移除监听
*
* @param removeListener 移除监听
*/
public void setRemoveListener(final Consumer<Map.Entry<K, V>> removeListener) {
this.removeListener = removeListener;
}
@Override @Override
protected boolean removeEldestEntry(final java.util.Map.Entry<K, V> eldest) { protected boolean removeEldestEntry(final java.util.Map.Entry<K, V> eldest) {
//当链表元素大于容量时移除最老最久未被使用的元素 //当链表元素大于容量时移除最老最久未被使用的元素
return size() > this.capacity; if (size() > this.capacity) {
if (null != removeListener) {
// 自定义监听
removeListener.accept(eldest);
}
return true;
}
return false;
} }
} }

View File

@ -1,6 +1,8 @@
package cn.hutool.core.cache; package cn.hutool.core.cache;
import cn.hutool.core.cache.impl.LRUCache; import cn.hutool.core.cache.impl.LRUCache;
import cn.hutool.core.lang.Console;
import cn.hutool.core.text.StrUtil;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import org.junit.Assert; import org.junit.Assert;
@ -64,4 +66,16 @@ public class LRUCacheTest {
} }
Assert.assertEquals("null123456789", sb2.toString()); Assert.assertEquals("null123456789", sb2.toString());
} }
@Test
public void issue2647Test(){
final LRUCache<String, Integer> cache = CacheUtil.newLRUCache(3,1);
cache.setListener((key, value) -> Console.log("Start remove k-v, key:{}, value:{}", key, value));
for (int i = 0; i < 10; i++) {
cache.put(StrUtil.format("key-{}", i), i);
}
Assert.assertEquals(3, cache.size());
}
} }