This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 3b4c1b2615 org.apache.juneau.common.reflect API improvements
3b4c1b2615 is described below
commit 3b4c1b2615f3268fc38934a54aac280fe2a95f73
Author: James Bognar <[email protected]>
AuthorDate: Thu Nov 20 13:52:53 2025 -0500
org.apache.juneau.common.reflect API improvements
---
.../apache/juneau/common/collections/Cache.java | 144 +++++------
.../apache/juneau/common/collections/Cache2.java | 89 ++++++-
.../apache/juneau/common/collections/Cache3.java | 87 ++++++-
.../apache/juneau/common/collections/Cache4.java | 90 ++++++-
.../apache/juneau/common/collections/Cache5.java | 93 ++++++-
.../common/collections/ConcurrentHashMap1Key.java | 134 ----------
.../common/collections/ConcurrentHashMap2Key.java | 163 ------------
.../common/collections/ConcurrentHashMap3Key.java | 165 -------------
.../common/collections/ConcurrentHashMap4Key.java | 171 -------------
.../common/collections/ConcurrentHashMap5Key.java | 149 -----------
.../juneau/common/collections/Cache2_Test.java | 23 +-
.../juneau/common/collections/Cache3_Test.java | 9 +-
.../juneau/common/collections/Cache4_Test.java | 9 +-
.../juneau/common/collections/Cache5_Test.java | 9 +-
.../juneau/common/collections/Cache_Test.java | 63 +++--
.../collections/ConcurrentHashMap2Key_Test.java | 272 ---------------------
.../collections/ConcurrentHashMap3Key_Test.java | 129 ----------
.../collections/ConcurrentHashMap4Key_Test.java | 132 ----------
.../collections/ConcurrentHashMap5Key_Test.java | 135 ----------
19 files changed, 465 insertions(+), 1601 deletions(-)
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
index 9fa526b204..5c48fd291c 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache.java
@@ -19,11 +19,15 @@ package org.apache.juneau.common.collections;
import static org.apache.juneau.common.utils.AssertionUtils.*;
import static org.apache.juneau.common.utils.SystemUtils.*;
import static org.apache.juneau.common.utils.Utils.*;
+import static java.util.Collections.*;
+import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.function.*;
+import org.apache.juneau.common.function.*;
+
/**
* Simple in-memory cache for storing and retrieving objects by key.
*
@@ -139,16 +143,39 @@ import java.util.function.*;
*
* <h5 class='section'>See Also:</h5>
* <ul>
- * <li class='jc'>{@link ConcurrentHashMap1Key}
* <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
* </ul>
*
* @param <K> The key type. Can be an array type for content-based key
matching.
* @param <V> The value type.
*/
-public class Cache<K,V> implements java.util.Map<K,V> {
+public class Cache<K,V> {
+
+ // Internal map with Tuple1 keys for content-based equality (especially
for arrays)
+ private final ConcurrentHashMap<Tuple1<K>,V> map = new
ConcurrentHashMap<>();
+
+ /**
+ * Cache of Tuple1 wrapper objects to minimize object creation on
repeated get/put calls.
+ *
+ * <p>
+ * Uses WeakHashMap so wrappers can be GC'd when keys are no longer
referenced.
+ * This provides a significant performance improvement for caches with
repeated key access.
+ */
+ private final Map<K,Tuple1<K>> wrapperCache = synchronizedMap(new
WeakHashMap<>());
- private final ConcurrentHashMap1Key<K,V> map = new
ConcurrentHashMap1Key<>();
+ /**
+ * Gets or creates a Tuple1 wrapper for the given key.
+ *
+ * <p>
+ * The Tuple1 wrapper provides content-based equality for arrays and
other objects.
+ * By caching these wrappers, we avoid creating new Tuple1 objects on
every cache access.
+ *
+ * @param key The key to wrap.
+ * @return A cached or new Tuple1 wrapper for the key.
+ */
+ private Tuple1<K> wrap(K key) {
+ return wrapperCache.computeIfAbsent(key, k -> Tuple1.of(k));
+ }
/**
* Builder for creating configured {@link Cache} instances.
@@ -435,11 +462,9 @@ public class Cache<K,V> implements java.util.Map<K,V> {
* @throws NullPointerException if no default supplier was configured.
* @throws IllegalArgumentException if key is <jk>null</jk>.
*/
- @SuppressWarnings("unchecked")
- @Override /* Map */
- public V get(Object key) {
+ public V get(K key) {
assertArgNotNull("key", key);
- return get((K)key, () -> supplier.apply((K)key));
+ return get(key, () -> supplier.apply(key));
}
/**
@@ -486,15 +511,16 @@ public class Cache<K,V> implements java.util.Map<K,V> {
assertArgNotNull("key", key);
if (disableCaching)
return supplier.get();
- V v = map.getKey(key);
+ Tuple1<K> wrapped = wrap(key);
+ V v = map.get(wrapped);
if (v == null) {
if (size() > maxSize)
clear();
v = supplier.get();
if (v == null)
- remove(key);
+ map.remove(wrapped);
else
- map.putKey(key, v);
+ map.putIfAbsent(wrapped, v);
} else {
cacheHits.incrementAndGet();
}
@@ -504,25 +530,16 @@ public class Cache<K,V> implements java.util.Map<K,V> {
/**
* Associates the specified value with the specified key in this cache.
*
- * <h5 class='section'>Example:</h5>
- * <p class='bjava'>
- * Cache<String,Pattern> <jv>cache</jv> =
Cache.<jsm>of</jsm>(String.<jk>class</jk>, Pattern.<jk>class</jk>).build();
- *
- * Pattern <jv>pattern</jv> = Pattern.compile(<js>"[0-9]+"</js>);
- * <jv>cache</jv>.put(<js>"digits"</js>, <jv>pattern</jv>);
- * </p>
- *
* @param key The cache key. Must not be <jk>null</jk>.
* @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping for the key.
+ * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
* @throws IllegalArgumentException if key is <jk>null</jk>.
*/
public V put(K key, V value) {
assertArgNotNull("key", key);
- return map.putKey(key, value);
+ return map.put(wrap(key), value);
}
-
/**
* Returns the total number of cache hits since this cache was created.
*
@@ -549,86 +566,75 @@ public class Cache<K,V> implements java.util.Map<K,V> {
*
* @return The total number of cache hits since creation.
*/
+ /**
+ * Returns the number of cache hits since creation.
+ *
+ * <p>
+ * A cache hit occurs when a value is retrieved from the cache without
needing to call the supplier.
+ *
+ * @return The number of cache hits.
+ */
public int getCacheHits() { return cacheHits.get(); }
/**
- * Returns the number of entries currently in the cache.
+ * Returns the number of entries in the cache.
*
* @return The number of cached entries.
*/
- @Override /* Map */
public int size() {
return map.size();
}
/**
- * Returns a collection view of the values contained in this cache.
+ * Returns <jk>true</jk> if the cache contains no entries.
*
- * @return A collection view of the values.
+ * @return <jk>true</jk> if the cache is empty.
*/
- @Override /* Map */
- public java.util.Collection<V> values() {
- return map.values();
+ public boolean isEmpty() {
+ return map.isEmpty();
}
/**
- * Returns <jk>true</jk> if this cache contains no entries.
+ * Returns <jk>true</jk> if the cache contains a mapping for the
specified key.
*
- * @return <jk>true</jk> if this cache contains no entries.
+ * @param key The key to check.
+ * @return <jk>true</jk> if the cache contains the key.
*/
- @Override /* Map */
- public boolean isEmpty() {
- return map.isEmpty();
+ public boolean containsKey(K key) {
+ return map.containsKey(wrap(key));
}
/**
- * Removes all entries from the cache.
+ * Returns <jk>true</jk> if the cache contains one or more entries with
the specified value.
*
- * <p>
- * Note: This does not reset the cache hit counter.
+ * @param value The value to check.
+ * @return <jk>true</jk> if the cache contains the value.
*/
- @Override /* Map */
- public void clear() {
- map.clear();
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
}
/**
- * Removes the specified key from the cache.
+ * Removes the entry for the specified key from the cache.
*
- * @param key The key to remove. Must not be <jk>null</jk>.
+ * @param key The key to remove.
* @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
* @throws IllegalArgumentException if key is <jk>null</jk>.
*/
- @Override /* Map */
- public V remove(Object key) {
+ public V remove(K key) {
assertArgNotNull("key", key);
- return
map.remove(org.apache.juneau.common.function.Tuple1.of(key));
+ Tuple1<K> wrapped = wrap(key);
+ V result = map.remove(wrapped);
+ wrapperCache.remove(key); // Clean up wrapper cache
+ return result;
}
- @Override /* Map */
- public boolean containsKey(Object key) {
- return
map.containsKey(org.apache.juneau.common.function.Tuple1.of(key));
- }
-
- @Override /* Map */
- public boolean containsValue(Object value) {
- return map.containsValue(value);
- }
-
- @Override /* Map */
- public void putAll(java.util.Map<? extends K, ? extends V> m) {
- m.forEach((k, v) -> put(k, v));
- }
-
- @Override /* Map */
- public java.util.Set<K> keySet() {
- return
map.keySet().stream().map(org.apache.juneau.common.function.Tuple1::getA).collect(java.util.stream.Collectors.toSet());
- }
-
- @Override /* Map */
- public java.util.Set<java.util.Map.Entry<K, V>> entrySet() {
- return map.entrySet().stream()
- .map(e -> new
java.util.AbstractMap.SimpleEntry<>(e.getKey().getA(), e.getValue()))
- .collect(java.util.stream.Collectors.toSet());
+ /**
+ * Removes all entries from the cache.
+ */
+ public void clear() {
+ map.clear();
+ wrapperCache.clear(); // Clean up wrapper cache
}
}
+
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
index e1f2db4d81..9d90fc8e48 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache2.java
@@ -123,17 +123,17 @@ import org.apache.juneau.common.function.*;
* <h5 class='section'>See Also:</h5>
* <ul>
* <li class='jc'>{@link Cache}
- * <li class='jc'>{@link ConcurrentHashMap2Key}
* <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
* </ul>
*
- * @param <K1> The first key type.
- * @param <K2> The second key type.
+ * @param <K1> The first key type. Can be an array type for content-based key
matching.
+ * @param <K2> The second key type. Can be an array type for content-based key
matching.
* @param <V> The value type.
*/
-public class Cache2<K1,K2,V> extends ConcurrentHashMap2Key<K1,K2,V> {
+public class Cache2<K1,K2,V> {
- private static final long serialVersionUID = 1L;
+ // Internal map with Tuple2 keys for content-based equality (especially
for arrays)
+ private final java.util.concurrent.ConcurrentHashMap<Tuple2<K1,K2>,V>
map = new java.util.concurrent.ConcurrentHashMap<>();
/**
* Builder for creating configured {@link Cache2} instances.
@@ -419,7 +419,6 @@ public class Cache2<K1,K2,V> extends
ConcurrentHashMap2Key<K1,K2,V> {
* @throws NullPointerException if no default supplier was configured.
* @throws IllegalArgumentException if key1 or key2 is <jk>null</jk>.
*/
- @Override /* ConcurrentHashMap2Key */
public V get(K1 key1, K2 key2) {
assertArgsNotNull("key1", key1, "key2", key2);
return get(key1, key2, () -> supplier.apply(key1, key2));
@@ -470,18 +469,92 @@ public class Cache2<K1,K2,V> extends
ConcurrentHashMap2Key<K1,K2,V> {
assertArgsNotNull("key1", key1, "key2", key2);
if (disableCaching)
return supplier.get();
- V v = super.get(key1, key2);
+ Tuple2<K1,K2> wrapped = Tuple2.of(key1, key2);
+ V v = map.get(wrapped);
if (v == null) {
if (size() > maxSize)
clear();
v = supplier.get();
- super.put(key1, key2, v);
+ map.putIfAbsent(wrapped, v);
} else {
cacheHits.incrementAndGet();
}
return v;
}
+ /**
+ * Associates the specified value with the specified key pair.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param value The value to associate with the key pair.
+ * @return The previous value associated with the key pair, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if key1 or key2 is <jk>null</jk>.
+ */
+ public V put(K1 key1, K2 key2, V value) {
+ assertArgsNotNull("key1", key1, "key2", key2);
+ return map.put(Tuple2.of(key1, key2), value);
+ }
+
+ /**
+ * Removes the entry for the specified key pair from the cache.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @return The previous value associated with the key pair, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if key1 or key2 is <jk>null</jk>.
+ */
+ public V remove(K1 key1, K2 key2) {
+ assertArgsNotNull("key1", key1, "key2", key2);
+ return map.remove(Tuple2.of(key1, key2));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains a mapping for the
specified key pair.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @return <jk>true</jk> if the cache contains the key pair.
+ */
+ public boolean containsKey(K1 key1, K2 key2) {
+ return map.containsKey(Tuple2.of(key1, key2));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains one or more entries with
the specified value.
+ *
+ * @param value The value to check.
+ * @return <jk>true</jk> if the cache contains the value.
+ */
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
+ }
+
+ /**
+ * Returns the number of entries in the cache.
+ *
+ * @return The number of cached entries.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains no entries.
+ *
+ * @return <jk>true</jk> if the cache is empty.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Removes all entries from the cache.
+ */
+ public void clear() {
+ map.clear();
+ }
+
/**
* Returns the total number of cache hits since this cache was created.
*
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
index 7eb912fee7..a018e4122e 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache3.java
@@ -74,9 +74,10 @@ import org.apache.juneau.common.function.*;
* @param <K3> The third key type.
* @param <V> The value type.
*/
-public class Cache3<K1,K2,K3,V> extends ConcurrentHashMap3Key<K1,K2,K3,V> {
+public class Cache3<K1,K2,K3,V> {
- private static final long serialVersionUID = 1L;
+ // Internal map with Tuple3 keys for content-based equality (especially
for arrays)
+ private final
java.util.concurrent.ConcurrentHashMap<Tuple3<K1,K2,K3>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
/**
* Builder for creating configured {@link Cache3} instances.
@@ -245,7 +246,6 @@ public class Cache3<K1,K2,K3,V> extends
ConcurrentHashMap3Key<K1,K2,K3,V> {
* @throws NullPointerException if no default supplier was configured.
* @throws IllegalArgumentException if any key is <jk>null</jk>.
*/
- @Override /* ConcurrentHashMap3Key */
public V get(K1 key1, K2 key2, K3 key3) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
return get(key1, key2, key3, () -> supplier.apply(key1, key2,
key3));
@@ -265,18 +265,95 @@ public class Cache3<K1,K2,K3,V> extends
ConcurrentHashMap3Key<K1,K2,K3,V> {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
if (disableCaching)
return supplier.get();
- V v = super.get(key1, key2, key3);
+ Tuple3<K1,K2,K3> wrapped = Tuple3.of(key1, key2, key3);
+ V v = map.get(wrapped);
if (v == null) {
if (size() > maxSize)
clear();
v = supplier.get();
- super.put(key1, key2, key3, v);
+ map.putIfAbsent(wrapped, v);
} else {
cacheHits.incrementAndGet();
}
return v;
}
+ /**
+ * Associates the specified value with the specified key triplet.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param value The value to associate with the key triplet.
+ * @return The previous value associated with the key triplet, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V put(K1 key1, K2 key2, K3 key3, V value) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
+ return map.put(Tuple3.of(key1, key2, key3), value);
+ }
+
+ /**
+ * Removes the entry for the specified key triplet from the cache.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @return The previous value associated with the key triplet, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V remove(K1 key1, K2 key2, K3 key3) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
+ return map.remove(Tuple3.of(key1, key2, key3));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains a mapping for the
specified key triplet.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @return <jk>true</jk> if the cache contains the key triplet.
+ */
+ public boolean containsKey(K1 key1, K2 key2, K3 key3) {
+ return map.containsKey(Tuple3.of(key1, key2, key3));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains one or more entries with
the specified value.
+ *
+ * @param value The value to check.
+ * @return <jk>true</jk> if the cache contains the value.
+ */
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
+ }
+
+ /**
+ * Returns the number of entries in the cache.
+ *
+ * @return The number of cached entries.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains no entries.
+ *
+ * @return <jk>true</jk> if the cache is empty.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Removes all entries from the cache.
+ */
+ public void clear() {
+ map.clear();
+ }
+
/**
* Returns the total number of cache hits since this cache was created.
*
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
index bc96ec1d29..3fda8bd97c 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache4.java
@@ -60,9 +60,10 @@ import org.apache.juneau.common.function.*;
* @param <K4> The fourth key type.
* @param <V> The value type.
*/
-public class Cache4<K1,K2,K3,K4,V> extends
ConcurrentHashMap4Key<K1,K2,K3,K4,V> {
+public class Cache4<K1,K2,K3,K4,V> {
- private static final long serialVersionUID = 1L;
+ // Internal map with Tuple4 keys for content-based equality (especially
for arrays)
+ private final
java.util.concurrent.ConcurrentHashMap<Tuple4<K1,K2,K3,K4>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
/**
* Builder for creating configured {@link Cache4} instances.
@@ -236,7 +237,6 @@ public class Cache4<K1,K2,K3,K4,V> extends
ConcurrentHashMap4Key<K1,K2,K3,K4,V>
* @throws NullPointerException if no default supplier was configured.
* @throws IllegalArgumentException if any key is <jk>null</jk>.
*/
- @Override /* ConcurrentHashMap4Key */
public V get(K1 key1, K2 key2, K3 key3, K4 key4) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
return get(key1, key2, key3, key4, () -> supplier.apply(key1,
key2, key3, key4));
@@ -257,18 +257,98 @@ public class Cache4<K1,K2,K3,K4,V> extends
ConcurrentHashMap4Key<K1,K2,K3,K4,V>
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
if (disableCaching)
return supplier.get();
- V v = super.get(key1, key2, key3, key4);
+ Tuple4<K1,K2,K3,K4> wrapped = Tuple4.of(key1, key2, key3, key4);
+ V v = map.get(wrapped);
if (v == null) {
if (size() > maxSize)
clear();
v = supplier.get();
- super.put(key1, key2, key3, key4, v);
+ map.putIfAbsent(wrapped, v);
} else {
cacheHits.incrementAndGet();
}
return v;
}
+ /**
+ * Associates the specified value with the specified four-part key.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @param value The value to associate with the four-part key.
+ * @return The previous value associated with the four-part key, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V put(K1 key1, K2 key2, K3 key3, K4 key4, V value) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
+ return map.put(Tuple4.of(key1, key2, key3, key4), value);
+ }
+
+ /**
+ * Removes the entry for the specified four-part key from the cache.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @return The previous value associated with the four-part key, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V remove(K1 key1, K2 key2, K3 key3, K4 key4) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
+ return map.remove(Tuple4.of(key1, key2, key3, key4));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains a mapping for the
specified four-part key.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @return <jk>true</jk> if the cache contains the four-part key.
+ */
+ public boolean containsKey(K1 key1, K2 key2, K3 key3, K4 key4) {
+ return map.containsKey(Tuple4.of(key1, key2, key3, key4));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains one or more entries with
the specified value.
+ *
+ * @param value The value to check.
+ * @return <jk>true</jk> if the cache contains the value.
+ */
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
+ }
+
+ /**
+ * Returns the number of entries in the cache.
+ *
+ * @return The number of cached entries.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains no entries.
+ *
+ * @return <jk>true</jk> if the cache is empty.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Removes all entries from the cache.
+ */
+ public void clear() {
+ map.clear();
+ }
+
/**
* Returns the total number of cache hits since this cache was created.
*
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
index 3596b28040..5c49ac6dfd 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/Cache5.java
@@ -62,9 +62,10 @@ import org.apache.juneau.common.function.*;
* @param <K5> The fifth key type.
* @param <V> The value type.
*/
-public class Cache5<K1,K2,K3,K4,K5,V> extends
ConcurrentHashMap5Key<K1,K2,K3,K4,K5,V> {
+public class Cache5<K1,K2,K3,K4,K5,V> {
- private static final long serialVersionUID = 1L;
+ // Internal map with Tuple5 keys for content-based equality (especially
for arrays)
+ private final
java.util.concurrent.ConcurrentHashMap<Tuple5<K1,K2,K3,K4,K5>,V> map = new
java.util.concurrent.ConcurrentHashMap<>();
/**
* Builder for creating configured {@link Cache5} instances.
@@ -243,7 +244,6 @@ public class Cache5<K1,K2,K3,K4,K5,V> extends
ConcurrentHashMap5Key<K1,K2,K3,K4,
* @throws NullPointerException if no default supplier was configured.
* @throws IllegalArgumentException if any key is <jk>null</jk>.
*/
- @Override /* ConcurrentHashMap5Key */
public V get(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5) {
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
return get(key1, key2, key3, key4, key5, () ->
supplier.apply(key1, key2, key3, key4, key5));
@@ -265,18 +265,101 @@ public class Cache5<K1,K2,K3,K4,K5,V> extends
ConcurrentHashMap5Key<K1,K2,K3,K4,
assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
if (disableCaching)
return supplier.get();
- V v = super.get(key1, key2, key3, key4, key5);
+ Tuple5<K1,K2,K3,K4,K5> wrapped = Tuple5.of(key1, key2, key3,
key4, key5);
+ V v = map.get(wrapped);
if (v == null) {
if (size() > maxSize)
clear();
v = supplier.get();
- super.put(key1, key2, key3, key4, key5, v);
+ map.putIfAbsent(wrapped, v);
} else {
cacheHits.incrementAndGet();
}
return v;
}
+ /**
+ * Associates the specified value with the specified five-part key.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @param key5 The fifth key.
+ * @param value The value to associate with the five-part key.
+ * @return The previous value associated with the five-part key, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V put(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, V value) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
+ return map.put(Tuple5.of(key1, key2, key3, key4, key5), value);
+ }
+
+ /**
+ * Removes the entry for the specified five-part key from the cache.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @param key5 The fifth key.
+ * @return The previous value associated with the five-part key, or
<jk>null</jk> if there was no mapping.
+ * @throws IllegalArgumentException if any key is <jk>null</jk>.
+ */
+ public V remove(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5) {
+ assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
+ return map.remove(Tuple5.of(key1, key2, key3, key4, key5));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains a mapping for the
specified five-part key.
+ *
+ * @param key1 The first key.
+ * @param key2 The second key.
+ * @param key3 The third key.
+ * @param key4 The fourth key.
+ * @param key5 The fifth key.
+ * @return <jk>true</jk> if the cache contains the five-part key.
+ */
+ public boolean containsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5)
{
+ return map.containsKey(Tuple5.of(key1, key2, key3, key4, key5));
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains one or more entries with
the specified value.
+ *
+ * @param value The value to check.
+ * @return <jk>true</jk> if the cache contains the value.
+ */
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
+ }
+
+ /**
+ * Returns the number of entries in the cache.
+ *
+ * @return The number of cached entries.
+ */
+ public int size() {
+ return map.size();
+ }
+
+ /**
+ * Returns <jk>true</jk> if the cache contains no entries.
+ *
+ * @return <jk>true</jk> if the cache is empty.
+ */
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ /**
+ * Removes all entries from the cache.
+ */
+ public void clear() {
+ map.clear();
+ }
+
/**
* Returns the total number of cache hits since this cache was created.
*
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap1Key.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap1Key.java
deleted file mode 100644
index a08e8c4b10..0000000000
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap1Key.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.common.utils.AssertionUtils.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.common.function.*;
-
-/**
- * A thread-safe concurrent hash map that uses a single-value wrapper key for
lookups.
- *
- * <p>
- * This class extends {@link ConcurrentHashMap} to provide efficient storage
and retrieval of values
- * indexed by a single key component wrapped in a {@link Tuple1}. The primary
use case is when you need
- * content-based equality for keys that would otherwise use identity-based
equality (such as arrays).
- *
- * <h5 class='section'>Features:</h5>
- * <ul class='spaced-list'>
- * <li><b>Content-Based Keys:</b> Keys use content-based equality via
{@link Tuple1}
- * <li><b>Array Support:</b> Arrays can be used as keys with proper
content-based hashing and equality
- * <li><b>Thread-Safe:</b> Inherits all thread-safety guarantees from
{@link ConcurrentHashMap}
- * <li><b>Null Keys Supported:</b> Key can be <jk>null</jk>
- * </ul>
- *
- * <h5 class='section'>Usage:</h5>
- * <p class='bjava'>
- * <jc>// Create a map for caching results indexed by array keys</jc>
- * ConcurrentHashMap1Key<String[],Result> <jv>cache</jv> =
- * <jk>new</jk> ConcurrentHashMap1Key<>();
- *
- * <jc>// Store a value</jc>
- * <jv>cache</jv>.put(<jk>new</jk> String[]{<js>"a"</js>, <js>"b"</js>},
<jv>result1</jv>);
- *
- * <jc>// Retrieve a value (works with different array instance but same
content)</jc>
- * Result <jv>cached</jv> = <jv>cache</jv>.get(<jk>new</jk>
String[]{<js>"a"</js>, <js>"b"</js>}); <jc>// Returns result1</jc>
- * </p>
- *
- * <h5 class='section'>Array Support:</h5>
- * <p>
- * Unlike standard {@link java.util.HashMap} which uses identity-based
equality for array keys,
- * this class properly handles arrays using content-based comparison:
- *
- * <p class='bjava'>
- * <jc>// Arrays work correctly as keys</jc>
- * ConcurrentHashMap1Key<int[],String> <jv>map</jv> = <jk>new</jk>
ConcurrentHashMap1Key<>();
- * <jv>map</jv>.put(<jk>new</jk> <jk>int</jk>[]{1,2,3}, <js>"foo"</js>);
- * String <jv>result</jv> = <jv>map</jv>.get(<jk>new</jk>
<jk>int</jk>[]{1,2,3}); <jc>// Returns "foo"</jc>
- * </p>
- *
- * <h5 class='section'>Common Use Cases:</h5>
- * <ul class='spaced-list'>
- * <li>Caching results indexed by array keys (e.g., annotation traversal
patterns)
- * <li>Storing configuration indexed by enum arrays
- * <li>Mapping results by method parameter arrays
- * <li>Any scenario requiring content-based equality for otherwise
identity-based types
- * </ul>
- *
- * <h5 class='section'>Key Hashing:</h5>
- * <p>
- * Keys are wrapped in {@link Tuple1} which provides content-based hashing.
- * For arrays, {@link java.util.Arrays#hashCode(Object[])} is used to ensure
- * consistent hashing based on array contents rather than identity.
- *
- * <h5 class='section'>Thread Safety:</h5>
- * <p>
- * This class inherits all thread-safety properties from {@link
ConcurrentHashMap}. Multiple threads
- * can safely read and write to the map concurrently without external
synchronization.
- *
- * <h5 class='section'>Performance:</h5>
- * <ul class='spaced-list'>
- * <li>Average O(1) lookup and insertion time (inherited from {@link
ConcurrentHashMap})
- * <li>Minimal object allocation: tuple keys are created only during
put/get operations
- * <li>Lock-free reads for existing entries (inherited from {@link
ConcurrentHashMap})
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * <li class='jc'>{@link ConcurrentHashMap2Key}
- * <li class='jc'>{@link ConcurrentHashMap3Key}
- * <li class='jc'>{@link ConcurrentHashMap4Key}
- * <li class='jc'>{@link ConcurrentHashMap5Key}
- * <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
- * </ul>
- *
- * @param <K> The key type.
- * @param <V> The value type.
- * @serial exclude
- */
-public class ConcurrentHashMap1Key<K,V> extends ConcurrentHashMap<Tuple1<K>,V>
{
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Retrieves the value associated with the specified key.
- *
- * @param key Key component. Must not be <jk>null</jk>.
- * @return The value associated with the key, or <jk>null</jk> if not
found.
- * @throws IllegalArgumentException if key is <jk>null</jk>.
- */
- public V getKey(K key) {
- assertArgNotNull("key", key);
- return super.get(Tuple1.of(key));
- }
-
- /**
- * Associates the specified value with the specified key in this map.
- *
- * @param key Key component. Must not be <jk>null</jk>.
- * @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
- * @throws IllegalArgumentException if key is <jk>null</jk>.
- */
- public V putKey(K key, V value) {
- assertArgNotNull("key", key);
- return super.put(Tuple1.of(key), value);
- }
-}
-
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key.java
deleted file mode 100644
index 5e172bc27f..0000000000
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.common.utils.AssertionUtils.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.common.function.*;
-
-/**
- * A thread-safe concurrent hash map that uses composite two-part keys for
lookups.
- *
- * <p>
- * This class extends {@link ConcurrentHashMap} to provide efficient storage
and retrieval of values
- * indexed by two separate key components. It's useful when you need to look
up values based on a
- * combination of two keys without creating intermediate wrapper objects.
- *
- * <h5 class='section'>Features:</h5>
- * <ul class='spaced-list'>
- * <li><b>Two-Part Keys:</b> Values are indexed by a pair of keys (K1, K2)
instead of a single key
- * <li><b>Content-Based Keys:</b> Keys use content-based equality via
{@link Tuple2}
- * <li><b>Array Support:</b> Arrays can be used as key components with
proper content-based hashing and equality
- * <li><b>Thread-Safe:</b> Inherits all thread-safety guarantees from
{@link ConcurrentHashMap}
- * <li><b>Null Keys Supported:</b> Both key parts can be <jk>null</jk>
- * </ul>
- *
- * <h5 class='section'>Usage:</h5>
- * <p class='bjava'>
- * <jc>// Create a map for storing class metadata indexed by ClassLoader
and Class</jc>
- * ConcurrentHashMap2Key<ClassLoader,Class<?>,ClassMeta>
<jv>map</jv> =
- * <jk>new</jk> ConcurrentHashMap2Key<>();
- *
- * <jc>// Store a value</jc>
- * <jv>map</jv>.put(<jv>classLoader</jv>, String.<jk>class</jk>,
<jv>stringMeta</jv>);
- *
- * <jc>// Retrieve a value</jc>
- * ClassMeta <jv>meta</jv> = <jv>map</jv>.get(<jv>classLoader</jv>,
String.<jk>class</jk>);
- * </p>
- *
- *
- * <h5 class='section'>Common Use Cases:</h5>
- * <ul class='spaced-list'>
- * <li>Caching class metadata indexed by ClassLoader and Class
- * <li>Storing configuration values indexed by environment and name
- * <li>Mapping database entities by table name and primary key
- * <li>Maintaining translation caches indexed by locale and message key
- * <li>Tracking statistics indexed by date and metric name
- * </ul>
- *
- * <h5 class='section'>Array Support:</h5>
- * <p>
- * Unlike standard {@link java.util.HashMap} which uses identity-based
equality for array keys,
- * this class properly handles arrays using content-based comparison via
{@link Tuple2}:
- *
- * <p class='bjava'>
- * <jc>// Arrays work correctly as key components</jc>
- * ConcurrentHashMap2Key<String,int[],Result> <jv>map</jv> =
<jk>new</jk> ConcurrentHashMap2Key<>();
- * <jv>map</jv>.put(<js>"key"</js>, <jk>new</jk> <jk>int</jk>[]{1,2,3},
<jv>result1</jv>);
- * Result <jv>r</jv> = <jv>map</jv>.get(<js>"key"</js>, <jk>new</jk>
<jk>int</jk>[]{1,2,3}); <jc>// Returns result1</jc>
- * </p>
- *
- * <h5 class='section'>Key Hashing:</h5>
- * <p>
- * Keys are wrapped in {@link Tuple2} which provides content-based hashing.
- * For arrays, {@link java.util.Arrays#hashCode(Object[])} is used to ensure
- * consistent hashing based on array contents rather than identity. Keys are
considered equal if both components
- * are equal according to content-based comparison (via {@link
org.apache.juneau.common.utils.Utils#eq(Object, Object)}).
- *
- * <h5 class='section'>Thread Safety:</h5>
- * <p>
- * This class inherits all thread-safety properties from {@link
ConcurrentHashMap}. Multiple threads
- * can safely read and write to the map concurrently without external
synchronization.
- *
- * <h5 class='section'>Performance:</h5>
- * <ul class='spaced-list'>
- * <li>Average O(1) lookup and insertion time (inherited from {@link
ConcurrentHashMap})
- * <li>Minimal object allocation: composite keys are created only during
put/get operations
- * <li>Lock-free reads for existing entries (inherited from {@link
ConcurrentHashMap})
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * <li class='jc'>{@link ConcurrentHashMap1Key}
- * <li class='jc'>{@link ConcurrentHashMap3Key}
- * <li class='jc'>{@link ConcurrentHashMap4Key}
- * <li class='jc'>{@link ConcurrentHashMap5Key}
- * <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
- * </ul>
- *
- * @param <K1> The first key component type. Can be an array type for
content-based key matching.
- * @param <K2> The second key component type. Can be an array type for
content-based key matching.
- * @param <V> The value type.
- * @serial exclude
- */
-public class ConcurrentHashMap2Key<K1,K2,V> extends
ConcurrentHashMap<Tuple2<K1,K2>,V> {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Retrieves the value associated with the specified two-part key.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bjava'>
- * ConcurrentHashMap2Key<String,Integer,User>
<jv>userMap</jv> =
- * <jk>new</jk> ConcurrentHashMap2Key<>();
- *
- * <jv>userMap</jv>.put(<js>"tenant1"</js>, 123, <jv>user1</jv>);
- *
- * User <jv>found</jv> = <jv>userMap</jv>.get(<js>"tenant1"</js>,
123); <jc>// Returns user1</jc>
- * User <jv>notFound</jv> =
<jv>userMap</jv>.get(<js>"tenant2"</js>, 456); <jc>// Returns null</jc>
- * </p>
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @return The value associated with the key, or <jk>null</jk> if not
found.
- * @throws IllegalArgumentException if key1 or key2 is <jk>null</jk>.
- */
- public V get(K1 key1, K2 key2) {
- assertArgsNotNull("key1", key1, "key2", key2);
- return super.get(Tuple2.of(key1, key2));
- }
-
- /**
- * Associates the specified value with the specified two-part key in
this map.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bjava'>
- * ConcurrentHashMap2Key<String,Integer,User>
<jv>userMap</jv> =
- * <jk>new</jk> ConcurrentHashMap2Key<>();
- *
- * User <jv>previousValue</jv> =
<jv>userMap</jv>.put(<js>"tenant1"</js>, 123, <jv>newUser</jv>);
- *
- * <jc>// Update existing entry</jc>
- * User <jv>oldUser</jv> =
<jv>userMap</jv>.put(<js>"tenant1"</js>, 123, <jv>updatedUser</jv>);
- * <jc>// oldUser contains the previous value (newUser)</jc>
- * </p>
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping for the key.
- * @throws IllegalArgumentException if key1 or key2 is <jk>null</jk>.
- */
- public V put(K1 key1, K2 key2, V value) {
- assertArgsNotNull("key1", key1, "key2", key2);
- return super.put(Tuple2.of(key1, key2), value);
- }
-}
\ No newline at end of file
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key.java
deleted file mode 100644
index 1fa97ff43a..0000000000
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.common.utils.AssertionUtils.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.common.function.*;
-
-/**
- * A thread-safe concurrent hash map that uses composite three-part keys for
lookups.
- *
- * <p>
- * This class extends {@link ConcurrentHashMap} to provide efficient storage
and retrieval of values
- * indexed by three separate key components. It's useful when you need to look
up values based on a
- * combination of three keys without creating intermediate wrapper objects.
- *
- * <h5 class='section'>Features:</h5>
- * <ul class='spaced-list'>
- * <li><b>Three-Part Keys:</b> Values are indexed by a triplet of keys
(K1, K2, K3) instead of a single key
- * <li><b>Content-Based Keys:</b> Keys use content-based equality via
{@link Tuple3}
- * <li><b>Array Support:</b> Arrays can be used as key components with
proper content-based hashing and equality
- * <li><b>Thread-Safe:</b> Inherits all thread-safety guarantees from
{@link ConcurrentHashMap}
- * </ul>
- *
- * <h5 class='section'>Usage:</h5>
- * <p class='bjava'>
- * <jc>// Create a map for caching translations by language, country, and
key</jc>
- * ConcurrentHashMap3Key<String,String,String,String>
<jv>translations</jv> =
- * <jk>new</jk> ConcurrentHashMap3Key<>();
- *
- * <jc>// Store a value</jc>
- * <jv>translations</jv>.put(<js>"en"</js>, <js>"US"</js>,
<js>"greeting"</js>, <js>"Hello"</js>);
- * <jv>translations</jv>.put(<js>"fr"</js>, <js>"FR"</js>,
<js>"greeting"</js>, <js>"Bonjour"</js>);
- *
- * <jc>// Retrieve values</jc>
- * String <jv>enGreeting</jv> = <jv>translations</jv>.get(<js>"en"</js>,
<js>"US"</js>, <js>"greeting"</js>);
- * </p>
- *
- * <h5 class='section'>With Supplier:</h5>
- * <p class='bjava'>
- * <jc>// Create a map that automatically loads translations</jc>
- * ConcurrentHashMap3Key<String,String,String,String> <jv>cache</jv>
=
- * <jk>new</jk> ConcurrentHashMap3Key<>(<jk>false</jk>,
(lang, country, key) ->
- * translationService.load(lang, country, key)
- * );
- *
- * <jc>// Automatically loads and caches if not present</jc>
- * String <jv>translation</jv> = <jv>cache</jv>.get(<js>"de"</js>,
<js>"DE"</js>, <js>"greeting"</js>);
- * </p>
- *
- * <h5 class='section'>Disabled Mode:</h5>
- * <p>
- * When constructed with <c>disabled=<jk>true</jk></c>, the map doesn't
actually store any values.
- * Instead, it always invokes the supplier function (if provided) or returns
<jk>null</jk>.
- * This is useful for testing or development scenarios where caching should be
bypassed.
- * </p>
- *
- * <p class='bjava'>
- * <jc>// Create a disabled cache (useful for testing)</jc>
- * ConcurrentHashMap3Key<String,String,String,String> <jv>cache</jv>
=
- * <jk>new</jk> ConcurrentHashMap3Key<>(<jk>true</jk>,
(lang, country, key) ->
- * translationService.load(lang, country, key)
- * );
- *
- * <jc>// Always calls translationService.load(), never caches</jc>
- * String <jv>translation</jv> = <jv>cache</jv>.get(<js>"de"</js>,
<js>"DE"</js>, <js>"greeting"</js>);
- * </p>
- *
- * <h5 class='section'>Common Use Cases:</h5>
- * <ul class='spaced-list'>
- * <li>Caching translations indexed by language, country, and message key
- * <li>Storing metrics indexed by date, category, and metric name
- * <li>Mapping configuration values by environment, tenant, and config key
- * <li>Caching query results indexed by database, schema, and query name
- * <li>Tracking permissions by user, resource, and action
- * </ul>
- *
- * <h5 class='section'>Array Support:</h5>
- * <p>
- * Unlike standard {@link java.util.HashMap} which uses identity-based
equality for array keys,
- * this class properly handles arrays using content-based comparison via
{@link Tuple3}.
- *
- * <h5 class='section'>Key Hashing:</h5>
- * <p>
- * Keys are wrapped in {@link Tuple3} which provides content-based hashing.
- * For arrays, {@link java.util.Arrays#hashCode(Object[])} is used to ensure
- * consistent hashing based on array contents rather than identity. Keys are
considered equal if all components
- * are equal according to content-based comparison (via {@link
org.apache.juneau.common.utils.Utils#eq(Object, Object)}).
- *
- * <h5 class='section'>Thread Safety:</h5>
- * <p>
- * This class inherits all thread-safety properties from {@link
ConcurrentHashMap}. Multiple threads
- * can safely read and write to the map concurrently without external
synchronization.
- *
- * <h5 class='section'>Performance:</h5>
- * <ul class='spaced-list'>
- * <li>Average O(1) lookup and insertion time (inherited from {@link
ConcurrentHashMap})
- * <li>Minimal object allocation: composite keys are created only during
put/get operations
- * <li>Lock-free reads for existing entries (inherited from {@link
ConcurrentHashMap})
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * <li class='jc'>{@link ConcurrentHashMap1Key}
- * <li class='jc'>{@link ConcurrentHashMap2Key}
- * <li class='jc'>{@link ConcurrentHashMap4Key}
- * <li class='jc'>{@link ConcurrentHashMap5Key}
- * <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
- * </ul>
- *
- * @param <K1> The first key component type. Can be an array type for
content-based key matching.
- * @param <K2> The second key component type. Can be an array type for
content-based key matching.
- * @param <K3> The third key component type. Can be an array type for
content-based key matching.
- * @param <V> The value type.
- * @serial exclude
- */
-public class ConcurrentHashMap3Key<K1,K2,K3,V> extends
ConcurrentHashMap<Tuple3<K1,K2,K3>,V> {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Retrieves the value associated with the specified three-part key.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @return The value associated with the key, or <jk>null</jk> if not
found.
- * @throws IllegalArgumentException if key1, key2, or key3 is
<jk>null</jk>.
- */
- public V get(K1 key1, K2 key2, K3 key3) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
- return super.get(Tuple3.of(key1, key2, key3));
- }
-
- /**
- * Associates the specified value with the specified three-part key in
this map.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
- * @throws IllegalArgumentException if key1, key2, or key3 is
<jk>null</jk>.
- */
- public V put(K1 key1, K2 key2, K3 key3, V value) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3);
- return super.put(Tuple3.of(key1, key2, key3), value);
- }
-}
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key.java
deleted file mode 100644
index c155fd6e5f..0000000000
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.common.utils.AssertionUtils.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.common.function.*;
-
-/**
- * A thread-safe concurrent hash map that uses composite four-part keys for
lookups.
- *
- * <p>
- * This class extends {@link ConcurrentHashMap} to provide efficient storage
and retrieval of values
- * indexed by four separate key components. It's useful when you need to look
up values based on a
- * combination of four keys without creating intermediate wrapper objects.
- *
- * <h5 class='section'>Features:</h5>
- * <ul class='spaced-list'>
- * <li><b>Four-Part Keys:</b> Values are indexed by four keys (K1, K2, K3,
K4) instead of a single key
- * <li><b>Content-Based Keys:</b> Keys use content-based equality via
{@link Tuple4}
- * <li><b>Array Support:</b> Arrays can be used as key components with
proper content-based hashing and equality
- * <li><b>Thread-Safe:</b> Inherits all thread-safety guarantees from
{@link ConcurrentHashMap}
- * <li><b>Null Keys Supported:</b> All key parts can be <jk>null</jk>
- * <li><b>Optional Caching:</b> Can be disabled to always invoke a
supplier function instead of caching
- * <li><b>Supplier Integration:</b> Optionally provides automatic value
computation via a {@link Function4}
- * </ul>
- *
- * <h5 class='section'>Usage:</h5>
- * <p class='bjava'>
- * <jc>// Create a map for caching permissions</jc>
- * ConcurrentHashMap4Key<String,String,String,String,Boolean>
<jv>permissions</jv> =
- * <jk>new</jk> ConcurrentHashMap4Key<>();
- *
- * <jc>// Store permissions: tenant, user, resource, action</jc>
- * <jv>permissions</jv>.put(<js>"tenant1"</js>, <js>"user123"</js>,
<js>"document"</js>, <js>"read"</js>, <jk>true</jk>);
- * <jv>permissions</jv>.put(<js>"tenant1"</js>, <js>"user123"</js>,
<js>"document"</js>, <js>"write"</js>, <jk>false</jk>);
- *
- * <jc>// Check permission</jc>
- * Boolean <jv>canRead</jv> = <jv>permissions</jv>.get(<js>"tenant1"</js>,
<js>"user123"</js>, <js>"document"</js>, <js>"read"</js>);
- * </p>
- *
- * <h5 class='section'>With Supplier:</h5>
- * <p class='bjava'>
- * <jc>// Create a map that automatically checks permissions</jc>
- * ConcurrentHashMap4Key<String,String,String,String,Boolean>
<jv>permCache</jv> =
- * <jk>new</jk> ConcurrentHashMap4Key<>(<jk>false</jk>,
(tenant, user, resource, action) ->
- * permissionService.check(tenant, user, resource, action)
- * );
- *
- * <jc>// Automatically checks and caches if not present</jc>
- * Boolean <jv>allowed</jv> = <jv>permCache</jv>.get(<js>"tenant1"</js>,
<js>"user123"</js>, <js>"document"</js>, <js>"write"</js>);
- * </p>
- *
- * <h5 class='section'>Disabled Mode:</h5>
- * <p>
- * When constructed with <c>disabled=<jk>true</jk></c>, the map doesn't
actually store any values.
- * Instead, it always invokes the supplier function (if provided) or returns
<jk>null</jk>.
- * This is useful for testing or development scenarios where caching should be
bypassed.
- * </p>
- *
- * <p class='bjava'>
- * <jc>// Create a disabled cache (useful for testing)</jc>
- * ConcurrentHashMap4Key<String,String,String,String,Boolean>
<jv>permCache</jv> =
- * <jk>new</jk> ConcurrentHashMap4Key<>(<jk>true</jk>,
(tenant, user, resource, action) ->
- * permissionService.check(tenant, user, resource, action)
- * );
- *
- * <jc>// Always calls permissionService.check(), never caches</jc>
- * Boolean <jv>allowed</jv> = <jv>permCache</jv>.get(<js>"tenant1"</js>,
<js>"user123"</js>, <js>"document"</js>, <js>"write"</js>);
- * </p>
- *
- * <h5 class='section'>Common Use Cases:</h5>
- * <ul class='spaced-list'>
- * <li>Caching permissions indexed by tenant, user, resource, and action
- * <li>Storing metrics indexed by environment, service, instance, and
metric name
- * <li>Mapping configuration by tenant, environment, service, and config
key
- * <li>Tracking analytics by date, source, campaign, and metric
- * <li>Caching query results indexed by database, schema, table, and query
type
- * </ul>
- *
- * <h5 class='section'>Array Support:</h5>
- * <p>
- * Unlike standard {@link java.util.HashMap} which uses identity-based
equality for array keys,
- * this class properly handles arrays using content-based comparison via
{@link Tuple4}.
- *
- * <h5 class='section'>Key Hashing:</h5>
- * <p>
- * Keys are wrapped in {@link Tuple4} which provides content-based hashing.
- * For arrays, {@link java.util.Arrays#hashCode(Object[])} is used to ensure
- * consistent hashing based on array contents rather than identity. Keys are
considered equal if all components
- * are equal according to content-based comparison (via {@link
org.apache.juneau.common.utils.Utils#eq(Object, Object)}).
- *
- * <h5 class='section'>Thread Safety:</h5>
- * <p>
- * This class inherits all thread-safety properties from {@link
ConcurrentHashMap}. Multiple threads
- * can safely read and write to the map concurrently without external
synchronization.
- *
- * <h5 class='section'>Performance:</h5>
- * <ul class='spaced-list'>
- * <li>Average O(1) lookup and insertion time (inherited from {@link
ConcurrentHashMap})
- * <li>Minimal object allocation: composite keys are created only during
put/get operations
- * <li>Lock-free reads for existing entries (inherited from {@link
ConcurrentHashMap})
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * <li class='jc'>{@link ConcurrentHashMap1Key}
- * <li class='jc'>{@link ConcurrentHashMap2Key}
- * <li class='jc'>{@link ConcurrentHashMap3Key}
- * <li class='jc'>{@link ConcurrentHashMap5Key}
- * <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
- * </ul>
- *
- * @param <K1> The first key component type. Can be an array type for
content-based key matching.
- * @param <K2> The second key component type. Can be an array type for
content-based key matching.
- * @param <K3> The third key component type. Can be an array type for
content-based key matching.
- * @param <K4> The fourth key component type. Can be an array type for
content-based key matching.
- * @param <V> The value type.
- * @serial exclude
- */
-public class ConcurrentHashMap4Key<K1,K2,K3,K4,V> extends
ConcurrentHashMap<Tuple4<K1,K2,K3,K4>,V> {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Retrieves the value associated with the specified four-part key.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @param key4 Fourth key component. Must not be <jk>null</jk>.
- * @return The value associated with the key, or <jk>null</jk> if not
found.
- * @throws IllegalArgumentException if any key is <jk>null</jk>.
- */
- public V get(K1 key1, K2 key2, K3 key3, K4 key4) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
- return super.get(Tuple4.of(key1, key2, key3, key4));
- }
-
- /**
- * Associates the specified value with the specified four-part key in
this map.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @param key4 Fourth key component. Must not be <jk>null</jk>.
- * @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
- * @throws IllegalArgumentException if any key is <jk>null</jk>.
- */
- public V put(K1 key1, K2 key2, K3 key3, K4 key4, V value) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4);
- return super.put(Tuple4.of(key1, key2, key3, key4), value);
- }
-}
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key.java
deleted file mode 100644
index 2995bd6597..0000000000
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.common.utils.AssertionUtils.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.common.function.*;
-
-/**
- * A thread-safe concurrent hash map that uses composite five-part keys for
lookups.
- *
- * <p>
- * This class extends {@link ConcurrentHashMap} to provide efficient storage
and retrieval of values
- * indexed by five separate key components. It's useful when you need to look
up values based on a
- * combination of five keys without creating intermediate wrapper objects.
- *
- * <h5 class='section'>Features:</h5>
- * <ul class='spaced-list'>
- * <li><b>Five-Part Keys:</b> Values are indexed by five keys (K1, K2, K3,
K4, K5) instead of a single key
- * <li><b>Content-Based Keys:</b> Keys use content-based equality via
{@link Tuple5}
- * <li><b>Array Support:</b> Arrays can be used as key components with
proper content-based hashing and equality
- * <li><b>Thread-Safe:</b> Inherits all thread-safety guarantees from
{@link ConcurrentHashMap}
- * <li><b>Null Keys Supported:</b> All key parts can be <jk>null</jk>
- * <li><b>Optional Caching:</b> Can be disabled to always invoke a
supplier function instead of caching
- * <li><b>Supplier Integration:</b> Optionally provides automatic value
computation via a {@link Function5}
- * </ul>
- *
- * <h5 class='section'>Usage:</h5>
- * <p class='bjava'>
- * <jc>// Create a map for caching complex queries</jc>
- *
ConcurrentHashMap5Key<String,String,String,String,String,ResultSet>
<jv>queryCache</jv> =
- * <jk>new</jk> ConcurrentHashMap5Key<>();
- *
- * <jc>// Store results: environment, database, schema, table,
operation</jc>
- * <jv>queryCache</jv>.put(<js>"prod"</js>, <js>"db1"</js>,
<js>"public"</js>, <js>"users"</js>, <js>"select"</js>, <jv>results</jv>);
- *
- * <jc>// Retrieve results</jc>
- * ResultSet <jv>cached</jv> = <jv>queryCache</jv>.get(<js>"prod"</js>,
<js>"db1"</js>, <js>"public"</js>, <js>"users"</js>, <js>"select"</js>);
- * </p>
- *
- * <h5 class='section'>With Supplier:</h5>
- * <p class='bjava'>
- * <jc>// Create a map that automatically executes queries</jc>
- *
ConcurrentHashMap5Key<String,String,String,String,String,ResultSet>
<jv>cache</jv> =
- * <jk>new</jk> ConcurrentHashMap5Key<>(<jk>false</jk>,
(env, db, schema, table, op) ->
- * queryService.execute(env, db, schema, table, op)
- * );
- *
- * <jc>// Automatically executes and caches if not present</jc>
- * ResultSet <jv>results</jv> = <jv>cache</jv>.get(<js>"prod"</js>,
<js>"db1"</js>, <js>"public"</js>, <js>"users"</js>, <js>"select"</js>);
- * </p>
- *
- * <h5 class='section'>Disabled Mode:</h5>
- * <p>
- * When constructed with <c>disabled=<jk>true</jk></c>, the map doesn't
actually store any values.
- * Instead, it always invokes the supplier function (if provided) or returns
<jk>null</jk>.
- * This is useful for testing or development scenarios where caching should be
bypassed.
- * </p>
- *
- * <p class='bjava'>
- * <jc>// Create a disabled cache (useful for testing)</jc>
- *
ConcurrentHashMap5Key<String,String,String,String,String,ResultSet>
<jv>cache</jv> =
- * <jk>new</jk> ConcurrentHashMap5Key<>(<jk>true</jk>, (env,
db, schema, table, op) ->
- * queryService.execute(env, db, schema, table, op)
- * );
- *
- * <jc>// Always calls queryService.execute(), never caches</jc>
- * ResultSet <jv>results</jv> = <jv>cache</jv>.get(<js>"prod"</js>,
<js>"db1"</js>, <js>"public"</js>, <js>"users"</js>, <js>"select"</js>);
- * </p>
- *
- * <h5 class='section'>Common Use Cases:</h5>
- * <ul class='spaced-list'>
- * <li>Caching database query results with complex composite keys
- * <li>Storing multi-dimensional analytics data
- * <li>Mapping highly granular configuration settings
- * <li>Tracking detailed audit logs or activity records
- * <li>Caching results from complex multi-parameter computations
- * </ul>
- *
- * <h5 class='section'>See Also:</h5>
- * <ul>
- * <li class='jc'>{@link ConcurrentHashMap1Key}
- * <li class='jc'>{@link ConcurrentHashMap2Key}
- * <li class='jc'>{@link ConcurrentHashMap3Key}
- * <li class='jc'>{@link ConcurrentHashMap4Key}
- * <li class='link'><a class="doclink"
href="../../../../../index.html#juneau-common">Overview > juneau-common</a>
- * </ul>
- *
- * @param <K1> The first key component type. Can be an array type for
content-based key matching.
- * @param <K2> The second key component type. Can be an array type for
content-based key matching.
- * @param <K3> The third key component type. Can be an array type for
content-based key matching.
- * @param <K4> The fourth key component type. Can be an array type for
content-based key matching.
- * @param <K5> The fifth key component type. Can be an array type for
content-based key matching.
- * @param <V> The value type.
- * @serial exclude
- */
-public class ConcurrentHashMap5Key<K1,K2,K3,K4,K5,V> extends
ConcurrentHashMap<Tuple5<K1,K2,K3,K4,K5>,V> {
-
- private static final long serialVersionUID = 1L;
-
- /**
- * Retrieves the value associated with the specified five-part key.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @param key4 Fourth key component. Must not be <jk>null</jk>.
- * @param key5 Fifth key component. Must not be <jk>null</jk>.
- * @return The value associated with the key, or <jk>null</jk> if not
found.
- * @throws IllegalArgumentException if any key is <jk>null</jk>.
- */
- public V get(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
- return super.get(Tuple5.of(key1, key2, key3, key4, key5));
- }
-
- /**
- * Associates the specified value with the specified five-part key in
this map.
- *
- * @param key1 First key component. Must not be <jk>null</jk>.
- * @param key2 Second key component. Must not be <jk>null</jk>.
- * @param key3 Third key component. Must not be <jk>null</jk>.
- * @param key4 Fourth key component. Must not be <jk>null</jk>.
- * @param key5 Fifth key component. Must not be <jk>null</jk>.
- * @param value The value to associate with the key.
- * @return The previous value associated with the key, or <jk>null</jk>
if there was no mapping.
- * @throws IllegalArgumentException if any key is <jk>null</jk>.
- */
- public V put(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, V value) {
- assertArgsNotNull("key1", key1, "key2", key2, "key3", key3,
"key4", key4, "key5", key5);
- return super.put(Tuple5.of(key1, key2, key3, key4, key5),
value);
- }
-}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
index 7f64c288d4..ceb708bb9d 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache2_Test.java
@@ -16,7 +16,6 @@
*/
package org.apache.juneau.common.collections;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.atomic.*;
@@ -44,7 +43,7 @@ class Cache2_Test extends TestBase {
assertEquals("user:123", result);
assertEquals(1, callCount.get());
- assertSize(1, x);
+ assertEquals(1, x.size());
assertEquals(0, x.getCacheHits());
}
@@ -68,7 +67,7 @@ class Cache2_Test extends TestBase {
assertEquals("user:123", result2);
assertSame(result1, result2);
assertEquals(1, callCount.get()); // Supplier only called once
- assertSize(1, x);
+ assertEquals(1, x.size());
assertEquals(1, x.getCacheHits());
}
@@ -90,7 +89,7 @@ class Cache2_Test extends TestBase {
assertEquals("admin:456", v2);
assertEquals("guest:789", v3);
assertEquals(3, callCount.get());
- assertSize(3, x);
+ assertEquals(3, x.size());
assertEquals(0, x.getCacheHits());
}
@@ -108,7 +107,7 @@ class Cache2_Test extends TestBase {
var result = x.get("user", 123, () -> "OVERRIDE");
assertEquals("OVERRIDE", result);
- assertSize(1, x);
+ assertEquals(1, x.size());
}
@Test
@@ -201,7 +200,7 @@ class Cache2_Test extends TestBase {
assertEquals("user:456", x.get("user", 456));
assertEquals(2, defaultCallCount.get()); // Called again
- assertEmpty(x); // Nothing cached
+ assertTrue(x.isEmpty()); // Nothing cached
}
//====================================================================================================
@@ -217,15 +216,15 @@ class Cache2_Test extends TestBase {
x.get("k1", 1);
x.get("k2", 2);
- assertSize(2, x);
+ assertEquals(2, x.size());
// Adding a third entry doesn't exceed maxSize (2 > 2 is false)
x.get("k3", 3);
- assertSize(3, x);
+ assertEquals(3, x.size());
// Fourth entry triggers clear (3 > 2 is true)
x.get("k4", 4);
- assertSize(1, x); // Only the new entry
+ assertEquals(1, x.size()); // Only the new entry
}
//====================================================================================================
@@ -266,11 +265,11 @@ class Cache2_Test extends TestBase {
x.get("user", 123);
x.get("admin", 456);
- assertSize(2, x);
+ assertEquals(2, x.size());
x.clear();
- assertEmpty(x);
+ assertTrue(x.isEmpty());
}
//====================================================================================================
@@ -291,7 +290,7 @@ class Cache2_Test extends TestBase {
var result = x.get("user", 123, () -> "CUSTOM");
assertEquals("CUSTOM", result);
- assertSize(1, x);
+ assertEquals(1, x.size());
}
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
index a5812974e6..6e1c3e48b2 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache3_Test.java
@@ -16,7 +16,6 @@
*/
package org.apache.juneau.common.collections;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.atomic.*;
@@ -86,7 +85,7 @@ class Cache3_Test extends TestBase {
x.get("en", "US", 1);
assertEquals(2, callCount.get()); // Called twice
- assertEmpty(x);
+ assertTrue(x.isEmpty());
}
@Test
@@ -98,13 +97,13 @@ class Cache3_Test extends TestBase {
x.get("en", "US", 1);
x.get("fr", "FR", 2);
- assertSize(2, x);
+ assertEquals(2, x.size());
x.get("de", "DE", 3);
- assertSize(3, x);
+ assertEquals(3, x.size());
x.get("es", "ES", 4); // This exceeds max (3 > 2)
- assertSize(1, x); // Cleared
+ assertEquals(1, x.size()); // Cleared
}
@Test
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
index 3ee615d9e4..2f879f6d3d 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache4_Test.java
@@ -16,7 +16,6 @@
*/
package org.apache.juneau.common.collections;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.atomic.*;
@@ -87,7 +86,7 @@ class Cache4_Test extends TestBase {
x.get("en", "US", "formal", 1);
assertEquals(2, callCount.get()); // Called twice
- assertEmpty(x);
+ assertTrue(x.isEmpty());
}
@Test
@@ -99,13 +98,13 @@ class Cache4_Test extends TestBase {
x.get("en", "US", "formal", 1);
x.get("fr", "FR", "formal", 2);
- assertSize(2, x);
+ assertEquals(2, x.size());
x.get("de", "DE", "formal", 3); // Doesn't exceed yet
- assertSize(3, x);
+ assertEquals(3, x.size());
x.get("es", "ES", "formal", 4); // Exceeds max (3 > 2),
triggers clear
- assertSize(1, x); // Cleared
+ assertEquals(1, x.size()); // Cleared
}
@Test
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
index c180211ee9..b78128c0bc 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache5_Test.java
@@ -16,7 +16,6 @@
*/
package org.apache.juneau.common.collections;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.atomic.*;
@@ -88,7 +87,7 @@ class Cache5_Test extends TestBase {
x.get("en", "US", "west", "formal", 1);
assertEquals(2, callCount.get()); // Called twice
- assertEmpty(x);
+ assertTrue(x.isEmpty());
}
@Test
@@ -100,13 +99,13 @@ class Cache5_Test extends TestBase {
x.get("en", "US", "west", "formal", 1);
x.get("fr", "FR", "north", "formal", 2);
- assertSize(2, x);
+ assertEquals(2, x.size());
x.get("de", "DE", "south", "formal", 3); // Doesn't exceed yet
- assertSize(3, x);
+ assertEquals(3, x.size());
x.get("es", "ES", "east", "formal", 4); // Exceeds max (3 > 2),
triggers clear
- assertSize(1, x); // Cleared
+ assertEquals(1, x.size()); // Cleared
}
@Test
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
index 4954cca8c4..1efe7be60a 100644
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
+++
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/Cache_Test.java
@@ -16,7 +16,6 @@
*/
package org.apache.juneau.common.collections;
-import static org.apache.juneau.junit.bct.BctAssertions.*;
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.*;
@@ -42,7 +41,7 @@ class Cache_Test extends TestBase {
assertEquals("value1", result);
assertEquals(1, callCount.get());
- assertSize(1, cache);
+ assertEquals(1, cache.size());
assertEquals(0, cache.getCacheHits());
}
@@ -66,7 +65,7 @@ class Cache_Test extends TestBase {
assertEquals("value1", result2);
assertSame(result1, result2); // Same instance
assertEquals(1, callCount.get()); // Supplier only called once
- assertSize(1, cache);
+ assertEquals(1, cache.size());
assertEquals(1, cache.getCacheHits());
}
@@ -80,7 +79,7 @@ class Cache_Test extends TestBase {
assertEquals(1, v1);
assertEquals(2, v2);
assertEquals(3, v3);
- assertSize(3, cache);
+ assertEquals(3, cache.size());
assertEquals(0, cache.getCacheHits());
// Verify all cached
@@ -113,20 +112,20 @@ class Cache_Test extends TestBase {
@Test void a06_size() {
var cache = Cache.of(String.class, Integer.class).build();
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
cache.get("one", () -> 1);
- assertSize(1, cache);
+ assertEquals(1, cache.size());
cache.get("two", () -> 2);
- assertSize(2, cache);
+ assertEquals(2, cache.size());
cache.get("three", () -> 3);
- assertSize(3, cache);
+ assertEquals(3, cache.size());
// Accessing existing key doesn't change size
cache.get("one", () -> 999);
- assertSize(3, cache);
+ assertEquals(3, cache.size());
}
@Test void a07_clear() {
@@ -136,18 +135,18 @@ class Cache_Test extends TestBase {
cache.get("two", () -> 2);
cache.get("one", () -> 999); // Cache hit
- assertSize(2, cache);
+ assertEquals(2, cache.size());
assertEquals(1, cache.getCacheHits());
cache.clear();
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
assertEquals(1, cache.getCacheHits()); // Hits not cleared
// Values must be recomputed after clear
var v1 = cache.get("one", () -> 10);
assertEquals(10, v1);
- assertSize(1, cache);
+ assertEquals(1, cache.size());
}
//====================================================================================================
@@ -162,15 +161,15 @@ class Cache_Test extends TestBase {
cache.get("one", () -> 1);
cache.get("two", () -> 2);
cache.get("three", () -> 3);
- assertSize(3, cache);
+ assertEquals(3, cache.size());
// 4th item doesn't trigger eviction (size > maxSize means 4 >
3)
cache.get("four", () -> 4);
- assertSize(4, cache);
+ assertEquals(4, cache.size());
// 5th item triggers eviction (size=4, 4 > 3, so clear then add)
cache.get("five", () -> 5);
- assertSize(1, cache); // Only the new item
+ assertEquals(1, cache.size()); // Only the new item
}
@Test void a09_maxSize_custom() {
@@ -182,15 +181,15 @@ class Cache_Test extends TestBase {
final int index = i;
cache.get("key" + index, () -> "value" + index);
}
- assertSize(5, cache);
+ assertEquals(5, cache.size());
// 6th item doesn't trigger clear yet (5 > 5 is false)
cache.get("key6", () -> "value6");
- assertSize(6, cache);
+ assertEquals(6, cache.size());
// 7th item triggers clear (6 > 5 is true)
cache.get("key7", () -> "value7");
- assertSize(1, cache);
+ assertEquals(1, cache.size());
}
//====================================================================================================
@@ -216,7 +215,7 @@ class Cache_Test extends TestBase {
assertEquals("value1", result1);
assertEquals("value2", result2);
assertEquals(2, callCount.get()); // Always calls supplier
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
assertEquals(0, cache.getCacheHits());
}
@@ -229,7 +228,7 @@ class Cache_Test extends TestBase {
cache.get("two", () -> 2);
cache.get("three", () -> 3);
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
}
@Test void a12_disabled_clearHasNoEffect() {
@@ -238,7 +237,7 @@ class Cache_Test extends TestBase {
.build();
cache.clear(); // Should not throw
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
}
//====================================================================================================
@@ -250,7 +249,7 @@ class Cache_Test extends TestBase {
// Should work with defaults
cache.get("key1", () -> "value1");
- assertSize(1, cache);
+ assertEquals(1, cache.size());
}
@Test void a14_builder_chaining() {
@@ -261,7 +260,7 @@ class Cache_Test extends TestBase {
// Disabled takes precedence
cache.get("key1", () -> "value1");
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
}
//====================================================================================================
@@ -328,7 +327,7 @@ class Cache_Test extends TestBase {
// Supplier might be called multiple times due to putIfAbsent
semantics,
// but should be much less than 100
assertTrue(callCount.get() < 10, "Supplier called " +
callCount.get() + " times");
- assertSize(1, cache);
+ assertEquals(1, cache.size());
executor.shutdown();
}
@@ -349,7 +348,7 @@ class Cache_Test extends TestBase {
// Wait for all tasks to complete
CompletableFuture.allOf(futures).get(5, TimeUnit.SECONDS);
- assertSize(10, cache);
+ assertEquals(10, cache.size());
executor.shutdown();
}
@@ -365,7 +364,7 @@ class Cache_Test extends TestBase {
cache.get(2, () -> "two");
assertEquals("one", cache.get(1, () -> "should not call"));
- assertSize(2, cache);
+ assertEquals(2, cache.size());
assertEquals(1, cache.getCacheHits());
}
@@ -376,7 +375,7 @@ class Cache_Test extends TestBase {
cache.get(Integer.class, () -> "Integer");
assertEquals("String", cache.get(String.class, () -> "should
not call"));
- assertSize(2, cache);
+ assertEquals(2, cache.size());
}
//====================================================================================================
@@ -391,16 +390,16 @@ class Cache_Test extends TestBase {
assertEquals("first", result1);
assertEquals("first", result2); // Returns cached, not "second"
- assertSize(1, cache);
+ assertEquals(1, cache.size());
}
@Test void a22_emptyCache_operations() {
var cache = Cache.of(String.class, String.class).build();
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
assertEquals(0, cache.getCacheHits());
cache.clear(); // Should not throw on empty cache
- assertEmpty(cache);
+ assertTrue(cache.isEmpty());
}
@Test void a23_maxSize_exactBoundary() {
@@ -412,12 +411,12 @@ class Cache_Test extends TestBase {
cache.get(2, () -> "two");
cache.get(3, () -> "three");
- assertSize(3, cache);
+ assertEquals(3, cache.size());
// Accessing existing keys shouldn't trigger eviction
cache.get(1, () -> "should not call");
cache.get(2, () -> "should not call");
- assertSize(3, cache);
+ assertEquals(3, cache.size());
assertEquals(2, cache.getCacheHits());
}
}
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key_Test.java
deleted file mode 100644
index d444ba3d2d..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap2Key_Test.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.junit.bct.BctAssertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.concurrent.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-class ConcurrentHashMap2Key_Test extends TestBase {
-
-
//====================================================================================================
- // a - Basic put and get operations
-
//====================================================================================================
-
- @Test
- void a01_basicPutAndGet() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- x.put("user", 123, "Alice");
- x.put("user", 456, "Bob");
- x.put("admin", 123, "Charlie");
-
- assertEquals("Alice", x.get("user", 123));
- assertEquals("Bob", x.get("user", 456));
- assertEquals("Charlie", x.get("admin", 123));
- }
-
- @Test
- void a02_getWithNonExistentKey() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- x.put("user", 123, "Alice");
-
- assertNull(x.get("user", 999));
- assertNull(x.get("admin", 123));
- }
-
- @Test
- void a03_updateExistingKey() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- assertNull(x.put("user", 123, "Alice"));
- assertEquals("Alice", x.put("user", 123, "AliceUpdated"));
- assertEquals("AliceUpdated", x.get("user", 123));
- }
-
-
//====================================================================================================
- // b - Null key validation
-
//====================================================================================================
-
- @Test
- void b01_nullKey1_get() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
123));
- }
-
- @Test
- void b02_nullKey2_get() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () ->
x.get("user", null));
- }
-
- @Test
- void b03_bothKeysNull_get() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
null));
- }
-
- @Test
- void b04_nullKey1_put() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
123, "value"));
- }
-
- @Test
- void b05_nullKey2_put() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () ->
x.put("user", null, "value"));
- }
-
- @Test
- void b06_bothKeysNull_put() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
null, "value"));
- }
-
-
//====================================================================================================
- // c - Key equality and hashing
-
//====================================================================================================
-
- @Test
- void c01_keyEquality_differentKeyParts() {
- var x = new ConcurrentHashMap2Key<String,String,String>();
-
- x.put("a", "b", "AB");
- x.put("b", "a", "BA");
-
- assertEquals("AB", x.get("a", "b"));
- assertEquals("BA", x.get("b", "a"));
- }
-
- @Test
- void c02_keyEquality_hashCollisions() {
- // Strings with same hash code
- var x = new ConcurrentHashMap2Key<String,String,String>();
-
- x.put("Aa", "BB", "value1");
- x.put("BB", "Aa", "value2");
-
- // Despite potential hash collision, should maintain distinct
entries
- assertEquals("value1", x.get("Aa", "BB"));
- assertEquals("value2", x.get("BB", "Aa"));
- }
-
-
//====================================================================================================
- // d - Size and containment
-
//====================================================================================================
-
- @Test
- void d01_sizeTracking() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- assertEmpty(x);
-
- x.put("user", 123, "Alice");
- assertSize(1, x);
-
- x.put("user", 456, "Bob");
- assertSize(2, x);
-
- x.put("admin", 123, "Charlie");
- assertSize(3, x);
-
- // Updating existing key doesn't change size
- x.put("user", 123, "AliceUpdated");
- assertSize(3, x);
- }
-
- @Test
- void d02_isEmpty() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- assertEmpty(x);
-
- x.put("user", 123, "Alice");
- assertNotEmpty(x);
-
- x.clear();
- assertEmpty(x);
- }
-
-
//====================================================================================================
- // e - Thread safety
-
//====================================================================================================
-
- @Test
- void e01_concurrentAccess() throws Exception {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
- var executor = Executors.newFixedThreadPool(10);
-
- // Submit 100 concurrent put operations
- var futures = new CompletableFuture[100];
- for (var i = 0; i < 100; i++) {
- final int index = i;
- futures[i] = CompletableFuture.runAsync(() -> {
- x.put("key" + (index % 10), index, "value" +
index);
- }, executor);
- }
-
- // Wait for all to complete
- CompletableFuture.allOf(futures).get(5, TimeUnit.SECONDS);
-
- // Verify all values are present
- for (var i = 0; i < 100; i++) {
- var value = x.get("key" + (i % 10), i);
- assertEquals("value" + i, value);
- }
-
- executor.shutdown();
- }
-
-
//====================================================================================================
- // f - Clear operation
-
//====================================================================================================
-
- @Test
- void f01_clear() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- x.put("user", 123, "Alice");
- x.put("user", 456, "Bob");
- x.put("admin", 123, "Charlie");
-
- assertSize(3, x);
-
- x.clear();
-
- assertEmpty(x);
- assertNull(x.get("user", 123));
- assertNull(x.get("user", 456));
- assertNull(x.get("admin", 123));
- }
-
-
//====================================================================================================
- // g - Different key types
-
//====================================================================================================
-
- @Test
- void g01_integerKeys() {
- var x = new ConcurrentHashMap2Key<Integer,Integer,String>();
-
- x.put(1, 2, "1:2");
- x.put(2, 1, "2:1");
-
- assertEquals("1:2", x.get(1, 2));
- assertEquals("2:1", x.get(2, 1));
- assertNull(x.get(1, 1));
- }
-
- @Test
- void g02_mixedKeyTypes() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- x.put("string", 123, "mixed1");
- x.put("another", 456, "mixed2");
-
- assertEquals("mixed1", x.get("string", 123));
- assertEquals("mixed2", x.get("another", 456));
- }
-
-
//====================================================================================================
- // h - Edge cases
-
//====================================================================================================
-
- @Test
- void h01_emptyMap() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- assertEmpty(x);
- assertEmpty(x);
- }
-
- @Test
- void h02_singleEntry() {
- var x = new ConcurrentHashMap2Key<String,Integer,String>();
-
- x.put("only", 1, "single");
-
- assertSize(1, x);
- assertEquals("single", x.get("only", 1));
- assertNull(x.get("only", 2));
- }
-}
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key_Test.java
deleted file mode 100644
index 8a88c16d2d..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap3Key_Test.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.junit.bct.BctAssertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-class ConcurrentHashMap3Key_Test extends TestBase {
-
-
//====================================================================================================
- // a - Basic put and get operations
-
//====================================================================================================
-
- @Test
- void a01_basicPutAndGet() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
-
- x.put("en", "US", 1, "Hello");
- x.put("en", "US", 2, "Goodbye");
- x.put("fr", "FR", 1, "Bonjour");
-
- assertEquals("Hello", x.get("en", "US", 1));
- assertEquals("Goodbye", x.get("en", "US", 2));
- assertEquals("Bonjour", x.get("fr", "FR", 1));
- }
-
- @Test
- void a02_getWithNonExistentKey() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
-
- x.put("en", "US", 1, "Hello");
-
- assertNull(x.get("en", "US", 999));
- assertNull(x.get("en", "UK", 1));
- assertNull(x.get("fr", "US", 1));
- }
-
- @Test
- void a03_updateExistingKey() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
-
- assertNull(x.put("en", "US", 1, "Hello"));
- assertEquals("Hello", x.put("en", "US", 1, "Hi"));
- assertEquals("Hi", x.get("en", "US", 1));
- }
-
-
//====================================================================================================
- // b - Null key validation
-
//====================================================================================================
-
- @Test
- void b01_nullKeys_get() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
"US", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
null, 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", null));
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
null, null));
- }
-
- @Test
- void b02_nullKeys_put() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
"US", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
null, 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", null, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
null, null, "value"));
- }
-
-
//====================================================================================================
- // c - Key distinctness
-
//====================================================================================================
-
- @Test
- void c01_keyOrdering() {
- var x = new
ConcurrentHashMap3Key<String,String,String,String>();
-
- x.put("a", "b", "c", "ABC");
- x.put("b", "c", "a", "BCA");
- x.put("c", "a", "b", "CAB");
-
- assertEquals("ABC", x.get("a", "b", "c"));
- assertEquals("BCA", x.get("b", "c", "a"));
- assertEquals("CAB", x.get("c", "a", "b"));
- }
-
-
//====================================================================================================
- // d - Size operations
-
//====================================================================================================
-
- @Test
- void d01_sizeTracking() {
- var x = new
ConcurrentHashMap3Key<String,String,Integer,String>();
-
- assertEmpty(x);
- assertEmpty(x);
-
- x.put("en", "US", 1, "Hello");
- assertSize(1, x);
- assertNotEmpty(x);
-
- x.put("en", "US", 2, "Goodbye");
- assertSize(2, x);
-
- x.put("en", "US", 1, "Hi"); // Update
- assertSize(2, x);
-
- x.clear();
- assertEmpty(x);
- assertEmpty(x);
- }
-}
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key_Test.java
deleted file mode 100644
index e69d4f19d0..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap4Key_Test.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.junit.bct.BctAssertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-class ConcurrentHashMap4Key_Test extends TestBase {
-
-
//====================================================================================================
- // a - Basic put and get operations
-
//====================================================================================================
-
- @Test
- void a01_basicPutAndGet() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
-
- x.put("en", "US", "formal", 1, "Hello");
- x.put("en", "US", "informal", 1, "Hi");
- x.put("fr", "FR", "formal", 1, "Bonjour");
-
- assertEquals("Hello", x.get("en", "US", "formal", 1));
- assertEquals("Hi", x.get("en", "US", "informal", 1));
- assertEquals("Bonjour", x.get("fr", "FR", "formal", 1));
- }
-
- @Test
- void a02_getWithNonExistentKey() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
-
- x.put("en", "US", "formal", 1, "Hello");
-
- assertNull(x.get("en", "US", "formal", 999));
- assertNull(x.get("en", "US", "informal", 1));
- assertNull(x.get("en", "UK", "formal", 1));
- assertNull(x.get("fr", "US", "formal", 1));
- }
-
- @Test
- void a03_updateExistingKey() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
-
- assertNull(x.put("en", "US", "formal", 1, "Hello"));
- assertEquals("Hello", x.put("en", "US", "formal", 1,
"Greetings"));
- assertEquals("Greetings", x.get("en", "US", "formal", 1));
- }
-
-
//====================================================================================================
- // b - Null key validation
-
//====================================================================================================
-
- @Test
- void b01_nullKeys_get() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
"US", "formal", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
null, "formal", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", null, 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", "formal", null));
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
null, null, null));
- }
-
- @Test
- void b02_nullKeys_put() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
"US", "formal", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
null, "formal", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", null, 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", "formal", null, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
null, null, null, "value"));
- }
-
-
//====================================================================================================
- // c - Key distinctness
-
//====================================================================================================
-
- @Test
- void c01_keyOrdering() {
- var x = new
ConcurrentHashMap4Key<String,String,String,String,String>();
-
- x.put("a", "b", "c", "d", "ABCD");
- x.put("d", "c", "b", "a", "DCBA");
- x.put("b", "a", "d", "c", "BADC");
-
- assertEquals("ABCD", x.get("a", "b", "c", "d"));
- assertEquals("DCBA", x.get("d", "c", "b", "a"));
- assertEquals("BADC", x.get("b", "a", "d", "c"));
- }
-
-
//====================================================================================================
- // d - Size operations
-
//====================================================================================================
-
- @Test
- void d01_sizeTracking() {
- var x = new
ConcurrentHashMap4Key<String,String,String,Integer,String>();
-
- assertEmpty(x);
- assertEmpty(x);
-
- x.put("en", "US", "formal", 1, "Hello");
- assertSize(1, x);
- assertNotEmpty(x);
-
- x.put("en", "US", "informal", 1, "Hi");
- assertSize(2, x);
-
- x.put("en", "US", "formal", 1, "Greetings"); // Update
- assertSize(2, x);
-
- x.clear();
- assertEmpty(x);
- assertEmpty(x);
- }
-}
-
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key_Test.java
b/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key_Test.java
deleted file mode 100644
index 96aad12ff3..0000000000
---
a/juneau-utest/src/test/java/org/apache/juneau/common/collections/ConcurrentHashMap5Key_Test.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.common.collections;
-
-import static org.apache.juneau.junit.bct.BctAssertions.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import org.apache.juneau.*;
-import org.junit.jupiter.api.*;
-
-class ConcurrentHashMap5Key_Test extends TestBase {
-
-
//====================================================================================================
- // a - Basic put and get operations
-
//====================================================================================================
-
- @Test
- void a01_basicPutAndGet() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
-
- x.put("en", "US", "west", "formal", 1, "Hello");
- x.put("en", "US", "west", "informal", 1, "Hi");
- x.put("fr", "FR", "north", "formal", 1, "Bonjour");
-
- assertEquals("Hello", x.get("en", "US", "west", "formal", 1));
- assertEquals("Hi", x.get("en", "US", "west", "informal", 1));
- assertEquals("Bonjour", x.get("fr", "FR", "north", "formal",
1));
- }
-
- @Test
- void a02_getWithNonExistentKey() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
-
- x.put("en", "US", "west", "formal", 1, "Hello");
-
- assertNull(x.get("en", "US", "west", "formal", 999));
- assertNull(x.get("en", "US", "west", "informal", 1));
- assertNull(x.get("en", "US", "east", "formal", 1));
- assertNull(x.get("en", "UK", "west", "formal", 1));
- assertNull(x.get("fr", "US", "west", "formal", 1));
- }
-
- @Test
- void a03_updateExistingKey() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
-
- assertNull(x.put("en", "US", "west", "formal", 1, "Hello"));
- assertEquals("Hello", x.put("en", "US", "west", "formal", 1,
"Greetings"));
- assertEquals("Greetings", x.get("en", "US", "west", "formal",
1));
- }
-
-
//====================================================================================================
- // b - Null key validation
-
//====================================================================================================
-
- @Test
- void b01_nullKeys_get() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
"US", "west", "formal", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
null, "west", "formal", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", null, "formal", 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", "west", null, 1));
- assertThrows(IllegalArgumentException.class, () -> x.get("en",
"US", "west", "formal", null));
- assertThrows(IllegalArgumentException.class, () -> x.get(null,
null, null, null, null));
- }
-
- @Test
- void b02_nullKeys_put() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
"US", "west", "formal", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
null, "west", "formal", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", null, "formal", 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", "west", null, 1, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put("en",
"US", "west", "formal", null, "value"));
- assertThrows(IllegalArgumentException.class, () -> x.put(null,
null, null, null, null, "value"));
- }
-
-
//====================================================================================================
- // c - Key distinctness
-
//====================================================================================================
-
- @Test
- void c01_keyOrdering() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,String,String>();
-
- x.put("a", "b", "c", "d", "e", "ABCDE");
- x.put("e", "d", "c", "b", "a", "EDCBA");
- x.put("c", "a", "e", "b", "d", "CAEBD");
-
- assertEquals("ABCDE", x.get("a", "b", "c", "d", "e"));
- assertEquals("EDCBA", x.get("e", "d", "c", "b", "a"));
- assertEquals("CAEBD", x.get("c", "a", "e", "b", "d"));
- }
-
-
//====================================================================================================
- // d - Size operations
-
//====================================================================================================
-
- @Test
- void d01_sizeTracking() {
- var x = new
ConcurrentHashMap5Key<String,String,String,String,Integer,String>();
-
- assertEmpty(x);
- assertEmpty(x);
-
- x.put("en", "US", "west", "formal", 1, "Hello");
- assertSize(1, x);
- assertNotEmpty(x);
-
- x.put("en", "US", "west", "informal", 1, "Hi");
- assertSize(2, x);
-
- x.put("en", "US", "west", "formal", 1, "Greetings"); // Update
- assertSize(2, x);
-
- x.clear();
- assertEmpty(x);
- assertEmpty(x);
- }
-}
-