diff --git a/README.md b/README.md index 45837724..7c2e667a 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ java-util Helpful Java utilities that are thoroughly tested and available on [Maven Central](https://central.sonatype.com/search?q=java-util&namespace=com.cedarsoftware). This library has no dependencies on other libraries for runtime. -The`.jar`file is `260K` and works with`JDK 1.8`through`JDK 21`. -The '.jar' file classes are version 52 (`JDK 1.8`). +The`.jar`file is `290K` and works with `JDK 1.8` through `JDK 22`. +The `.jar` file classes are version 52 `(JDK 1.8)` ## Compatibility ### JPMS (Java Platform Module System) @@ -25,7 +25,7 @@ Both of these features ensure that our library can be seamlessly integrated into To include in your project: ##### Gradle ```groovy -implementation 'com.cedarsoftware:java-util:2.11.0' +implementation 'com.cedarsoftware:java-util:2.12.0' ``` ##### Maven @@ -33,7 +33,7 @@ implementation 'com.cedarsoftware:java-util:2.11.0' com.cedarsoftware java-util - 2.11.0 + 2.12.0 ``` --- @@ -60,7 +60,7 @@ Included in java-util: - **[CompactCILinkedMap](/src/main/java/com/cedarsoftware/util/CompactCILinkedMap.java)** - A small-footprint, case-insensitive `Map` that becomes a `LinkedHashMap`. - **[CompactCIHashMap](/src/main/java/com/cedarsoftware/util/CompactCIHashMap.java)** - A compact, case-insensitive `Map` expanding to a `HashMap`. - **[CaseInsensitiveMap](/src/main/java/com/cedarsoftware/util/CaseInsensitiveMap.java)** - Treats `String` keys in a case-insensitive manner. -- **[LRUCache](/src/main/java/com/cedarsoftware/util/LRUCache.java)** - A thread-safe LRU cache implementing the full Map API, managing items based on usage. +- **[LRUCache](/src/main/java/com/cedarsoftware/util/LRUCache.java)** - Thread-safe LRU cache which implements the Map API. Supports "locking" or "threaded" strategy (selectable). - **[TrackingMap](/src/main/java/com/cedarsoftware/util/TrackingMap.java)** - Tracks access patterns to its keys, aiding in performance optimizations. - **[SealableMap](/src/main/java/com/cedarsoftware/util/SealableMap.java)** - Allows toggling between sealed (read-only) and unsealed (writable) states, managed externally. - **[SealableNavigableMap](/src/main/java/com/cedarsoftware/util/SealableNavigableMap.java)** - Extends `SealableMap` features to `NavigableMap`, managing state externally. diff --git a/changelog.md b/changelog.md index 151a41d1..183a246d 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,6 @@ ### Revision History +* 2.12.0 + * `LRUCache` updated to support both "locking" and "threaded" implementation strategies. * 2.11.0 * `LRUCache` re-written so that it operates in O(1) for `get(),` `put(),` and `remove()` methods without thread contention. When items are placed into (or removed from) the cache, it schedules a cleanup task to trim the cache to its capacity. This means that it will operate as fast as a `ConcurrentHashMap,` yet shrink to capacity quickly after modifications. * 2.10.0 diff --git a/pom.xml b/pom.xml index 5d80af63..21609eda 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.cedarsoftware java-util bundle - 2.11.0 + 2.12.0 Java Utilities https://github.com/jdereg/java-util @@ -37,7 +37,7 @@ 5.10.2 4.11.0 3.26.0 - 4.24.0 + 4.25.0 1.21.2 diff --git a/src/main/java/com/cedarsoftware/util/LRUCache.java b/src/main/java/com/cedarsoftware/util/LRUCache.java index 0a3d92cc..002c0a40 100644 --- a/src/main/java/com/cedarsoftware/util/LRUCache.java +++ b/src/main/java/com/cedarsoftware/util/LRUCache.java @@ -17,23 +17,53 @@ public enum StrategyType { LOCKING } + /** + * Create a "locking-based" LRUCache with the passed in capacity. + * @param capacity int maximum number of entries in the cache. + * @see com.cedarsoftware.util.cache.LockingLRUCacheStrategy + */ + public LRUCache(int capacity) { + strategy = new LockingLRUCacheStrategy<>(capacity); + } + + /** + * Create a "locking-based" OR a "thread-based" LRUCache with the passed in capacity. + *

+ * Note: There is a "shutdown" method on LRUCache to ensure that the default scheduler that was created for you + * is cleaned up, which is useful in a container environment. + * @param capacity int maximum number of entries in the cache. + * @param strategyType StrategyType.LOCKING or Strategy.THREADED indicating the underlying LRUCache implementation. + * @see com.cedarsoftware.util.cache.LockingLRUCacheStrategy + * @see com.cedarsoftware.util.cache.ThreadedLRUCacheStrategy + */ public LRUCache(int capacity, StrategyType strategyType) { - this(capacity, strategyType, 10, null, null); - } - - public LRUCache(int capacity, StrategyType strategyType, int cleanupDelayMillis, ScheduledExecutorService scheduler, ForkJoinPool cleanupPool) { - switch (strategyType) { - case THREADED: - this.strategy = new ThreadedLRUCacheStrategy<>(capacity, cleanupDelayMillis, scheduler, cleanupPool); - break; - case LOCKING: - this.strategy = new LockingLRUCacheStrategy<>(capacity); - break; - default: - throw new IllegalArgumentException("Unknown strategy type"); + if (strategyType == StrategyType.THREADED) { + strategy = new ThreadedLRUCacheStrategy<>(capacity, 10, null, null); + } else if (strategyType == StrategyType.LOCKING) { + strategy = new LockingLRUCacheStrategy<>(capacity); + } else { + throw new IllegalArgumentException("Unsupported strategy type: " + strategyType); } } + /** + * Create a "thread-based" LRUCache with the passed in capacity. + *

+ * Note: There is a "shutdown" method on LRUCache to ensure that the default scheduler that was created for you + * is cleaned up, which is useful in a container environment. If you supplied your own scheduler and cleanupPool, + * then it is up to you to manage there termination. The shutdown() method will not manipulate them in anyway. + * @param capacity int maximum number of entries in the cache. + * @param cleanupDelayMillis int number of milliseconds after a put() call when a scheduled task should run to + * trim the cache to no more than capacity. The default is 10ms. + * @param scheduler ScheduledExecutorService which can be null, in which case one will be created for you, or you + * can supply your own. + * @param cleanupPool ForkJoinPool can be null, in which case one will be created for you, you can supply your own. + * @see com.cedarsoftware.util.cache.ThreadedLRUCacheStrategy + */ + public LRUCache(int capacity, int cleanupDelayMillis, ScheduledExecutorService scheduler, ForkJoinPool cleanupPool) { + strategy = new ThreadedLRUCacheStrategy<>(capacity, cleanupDelayMillis, scheduler, cleanupPool); + } + @Override public V get(Object key) { return strategy.get(key); @@ -51,7 +81,7 @@ public void putAll(Map m) { @Override public V remove(Object key) { - return strategy.remove((K)key); + return strategy.remove(key); } @Override @@ -71,12 +101,12 @@ public boolean isEmpty() { @Override public boolean containsKey(Object key) { - return strategy.containsKey((K)key); + return strategy.containsKey(key); } @Override public boolean containsValue(Object value) { - return strategy.containsValue((V)value); + return strategy.containsValue(value); } @Override @@ -106,7 +136,14 @@ public int hashCode() { @Override public boolean equals(Object obj) { - return strategy.equals(obj); + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + LRUCache other = (LRUCache) obj; + return strategy.equals(other.strategy); } public void shutdown() {