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 &gt; 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&lt;String,Pattern&gt; <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 &gt; 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&lt;String[],Result&gt; <jv>cache</jv> =
- *             <jk>new</jk> ConcurrentHashMap1Key&lt;&gt;();
- *
- *     <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&lt;int[],String&gt; <jv>map</jv> = <jk>new</jk> 
ConcurrentHashMap1Key&lt;&gt;();
- *     <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 &gt; 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&lt;ClassLoader,Class&lt;?&gt;,ClassMeta&gt; 
<jv>map</jv> =
- *             <jk>new</jk> ConcurrentHashMap2Key&lt;&gt;();
- *
- *     <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&lt;String,int[],Result&gt; <jv>map</jv> = 
<jk>new</jk> ConcurrentHashMap2Key&lt;&gt;();
- *     <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 &gt; 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&lt;String,Integer,User&gt; 
<jv>userMap</jv> =
-        *              <jk>new</jk> ConcurrentHashMap2Key&lt;&gt;();
-        *
-        *      <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&lt;String,Integer,User&gt; 
<jv>userMap</jv> =
-        *              <jk>new</jk> ConcurrentHashMap2Key&lt;&gt;();
-        *
-        *      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&lt;String,String,String,String&gt; 
<jv>translations</jv> =
- *             <jk>new</jk> ConcurrentHashMap3Key&lt;&gt;();
- *
- *     <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&lt;String,String,String,String&gt; <jv>cache</jv> 
=
- *             <jk>new</jk> ConcurrentHashMap3Key&lt;&gt;(<jk>false</jk>, 
(lang, country, key) -&gt;
- *                     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&lt;String,String,String,String&gt; <jv>cache</jv> 
=
- *             <jk>new</jk> ConcurrentHashMap3Key&lt;&gt;(<jk>true</jk>, 
(lang, country, key) -&gt;
- *                     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 &gt; 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&lt;String,String,String,String,Boolean&gt; 
<jv>permissions</jv> =
- *             <jk>new</jk> ConcurrentHashMap4Key&lt;&gt;();
- *
- *     <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&lt;String,String,String,String,Boolean&gt; 
<jv>permCache</jv> =
- *             <jk>new</jk> ConcurrentHashMap4Key&lt;&gt;(<jk>false</jk>, 
(tenant, user, resource, action) -&gt;
- *                     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&lt;String,String,String,String,Boolean&gt; 
<jv>permCache</jv> =
- *             <jk>new</jk> ConcurrentHashMap4Key&lt;&gt;(<jk>true</jk>, 
(tenant, user, resource, action) -&gt;
- *                     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 &gt; 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&lt;String,String,String,String,String,ResultSet&gt; 
<jv>queryCache</jv> =
- *             <jk>new</jk> ConcurrentHashMap5Key&lt;&gt;();
- *
- *     <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&lt;String,String,String,String,String,ResultSet&gt; 
<jv>cache</jv> =
- *             <jk>new</jk> ConcurrentHashMap5Key&lt;&gt;(<jk>false</jk>, 
(env, db, schema, table, op) -&gt;
- *                     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&lt;String,String,String,String,String,ResultSet&gt; 
<jv>cache</jv> =
- *             <jk>new</jk> ConcurrentHashMap5Key&lt;&gt;(<jk>true</jk>, (env, 
db, schema, table, op) -&gt;
- *                     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 &gt; 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);
-       }
-}
-

Reply via email to