diff --git a/hutool-core/src/main/java/cn/hutool/core/cache/impl/LRUCache.java b/hutool-core/src/main/java/cn/hutool/core/cache/impl/LRUCache.java index 9f4b8cb35..a25728b4a 100755 --- a/hutool-core/src/main/java/cn/hutool/core/cache/impl/LRUCache.java +++ b/hutool-core/src/main/java/cn/hutool/core/cache/impl/LRUCache.java @@ -1,5 +1,6 @@ package cn.hutool.core.cache.impl; +import cn.hutool.core.lang.mutable.Mutable; import cn.hutool.core.map.FixedLinkedHashMap; import java.util.Iterator; @@ -42,7 +43,13 @@ public class LRUCache extends ReentrantCache { this.timeout = timeout; //链表key按照访问顺序排序,调用get方法后,会将这次访问的元素移至头部 - cacheMap = new FixedLinkedHashMap<>(capacity); + final FixedLinkedHashMap, CacheObj> fixedLinkedHashMap = new FixedLinkedHashMap<>(capacity); + fixedLinkedHashMap.setRemoveListener(entry -> { + if(null != listener){ + listener.onRemove(entry.getKey().get(), entry.getValue().getValue()); + } + }); + cacheMap = fixedLinkedHashMap; } // ---------------------------------------------------------------- prune diff --git a/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java b/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java index 1ef475ae5..a66321378 100644 --- a/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/FixedLinkedHashMap.java @@ -1,21 +1,28 @@ package cn.hutool.core.map; import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Consumer; /** * 固定大小的{@link LinkedHashMap} 实现
* 注意此类非线程安全,由于{@link #get(Object)}操作会修改链表的顺序结构,因此也不可以使用读写锁。 * - * @author looly - * * @param 键类型 * @param 值类型 + * @author looly */ public class FixedLinkedHashMap extends LinkedHashMap { private static final long serialVersionUID = -629171177321416095L; - /** 容量,超过此容量自动删除末尾元素 */ + /** + * 容量,超过此容量自动删除末尾元素 + */ private int capacity; + /** + * 移除监听 + */ + private Consumer> removeListener; /** * 构造 @@ -45,10 +52,25 @@ public class FixedLinkedHashMap extends LinkedHashMap { this.capacity = capacity; } + /** + * 设置自定义移除监听 + * + * @param removeListener 移除监听 + */ + public void setRemoveListener(final Consumer> removeListener) { + this.removeListener = removeListener; + } + @Override protected boolean removeEldestEntry(final java.util.Map.Entry eldest) { //当链表元素大于容量时,移除最老(最久未被使用)的元素 - return size() > this.capacity; + if (size() > this.capacity) { + if (null != removeListener) { + // 自定义监听 + removeListener.accept(eldest); + } + return true; + } + return false; } - } diff --git a/hutool-core/src/test/java/cn/hutool/core/cache/LRUCacheTest.java b/hutool-core/src/test/java/cn/hutool/core/cache/LRUCacheTest.java index 62664faa5..a981e4fd1 100755 --- a/hutool-core/src/test/java/cn/hutool/core/cache/LRUCacheTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/cache/LRUCacheTest.java @@ -1,6 +1,8 @@ package cn.hutool.core.cache; 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.util.RandomUtil; import org.junit.Assert; @@ -64,4 +66,16 @@ public class LRUCacheTest { } Assert.assertEquals("null123456789", sb2.toString()); } + + @Test + public void issue2647Test(){ + final LRUCache 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()); + } }