_Maps { public static <K, V> AliasMap<K, V> newAliasMap( final Supplier<Map<K, V>> mapFactory){ _With.requires(mapFactory, "mapFactory"); return new AliasMap<K, V>() { final Map<K, V> delegate = mapFactory.get(); @Override public int size() { return delegate.size(); } @Override public boolean isEmpty() { return delegate.isEmpty(); } @Override public boolean containsValue(Object value) { return delegate.containsValue(value); } @Override public Set<K> keySet() { return delegate.keySet(); } @Override public Collection<V> values() { return delegate.values(); } @Override public Set<Entry<K, V>> entrySet() { return delegate.entrySet(); } @Override public V put(K key, V value) { return this.put(key, Can.empty(), value); } @Override public void putAll(Map<? extends K, ? extends V> other) { if(!_NullSafe.isEmpty(other)) { other.forEach((k, v)->this.put(k, v)); } } @Override public V put(K key, Can<K> aliases, V value) { putAliasKeys(key, aliases, false); return delegate.put(key, value); } @Override public V remap(K key, Can<K> aliases, V value) { putAliasKeys(key, aliases, true); return delegate.put(key, value); } @Override public boolean containsKey(Object keyOrAliasKey) { return delegate.containsKey(keyOrAliasKey) || containsAliasKey(keyOrAliasKey); } @Override public V get(Object keyOrAliasKey) { val v = delegate.get(keyOrAliasKey); if(v!=null) { return v; } return getByAliasKey(keyOrAliasKey); } @Override public V remove(Object key) { removeAliasKeysOf(key); return delegate.remove(key); } @Override public void clear() { delegate.clear(); clearAliasKeys(); } private final Map<K, KeyPair<K>> pairByAliasKey = _Maps.newHashMap(); private void putAliasKeys(K key, Can<K> aliasKeys, boolean remap) { if(aliasKeys.isNotEmpty()) { val keyPair = KeyPair.of(key, aliasKeys); for(val aliasKey : aliasKeys) { val existingKeyPair = pairByAliasKey.put(aliasKey, keyPair); if(existingKeyPair!=null && !remap) { throw _Exceptions.illegalArgument( "alias key collision on alias %s: existing-key=%s, new-key=%s", aliasKey, existingKeyPair.key, keyPair.key); } } } } private V getByAliasKey(Object aliasKey) { val keyPair = pairByAliasKey.get(aliasKey); if(keyPair!=null) { return delegate.get(keyPair.getKey()); } return null; } private boolean containsAliasKey(Object aliasKey) { return pairByAliasKey.containsKey(aliasKey); } private void removeAliasKeysOf(final Object key) { pairByAliasKey.entrySet() .removeIf(entry->{ val keyPair = entry.getValue(); return keyPair.getKey().equals(key); }); } private void clearAliasKeys() { pairByAliasKey.clear(); } }; } private  _Maps(); static Map<K, V> unmodifiable(K k1, V v1); static Map<K, V> unmodifiable(K k1, V v1, K k2, V v2); static Map<K, V> unmodifiable(K k1, V v1, K k2, V v2, K k3, V v3); static Map<K, V> unmodifiable(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4); @SafeVarargs static Map<K, V> unmodifiableEntries(Map.Entry<? extends K,? extends V>... entries); static Map.Entry<K, V> entry(K k, V v); static boolean toggleElement(
            @NonNull Map<K, V> map, 
            @NonNull K key, 
            @NonNull V value); static Map<K, V> filterKeys(
            @Nullable Map<K, V> input,
            Predicate<K> keyFilter, 
            Supplier<Map<K, V>> factory); static ListMultimap<V, K> invertToListMultimap(Map<K, V> input); static HashMap<K, V> newHashMap(); static LinkedHashMap<K, V> newLinkedHashMap(); static ConcurrentHashMap<K, V> newConcurrentHashMap(); static TreeMap<K, V> newTreeMap(); static TreeMap<K, V> newTreeMap(Comparator<? super K> comparator); static AliasMap<K, V> newAliasMap(
            final Supplier<Map<K, V>> mapFactory);  }
@Test void aliasMap_shouldAllowLookupByAliasKey() { val aliasMap = _Maps.<String, String>newAliasMap(HashMap::new); aliasMap.put("key1", "value1"); aliasMap.put("key2", Can.ofArray(new String[] {"alias2a", "alias2b"}), "value2"); aliasMap.put("key3", Can.empty(), "value3"); assertTrue(aliasMap.containsKey("key1")); assertEquals("value1", aliasMap.get("key1")); assertTrue(aliasMap.containsKey("key2")); assertEquals("value2", aliasMap.get("key2")); assertEquals("value2", aliasMap.get("alias2a")); assertEquals("value2", aliasMap.get("alias2b")); assertTrue(aliasMap.containsKey("key3")); assertEquals("value3", aliasMap.get("key3")); }
@Test void aliasMap_shouldAlsoClearAliases() { val aliasMap = _Maps.<String, String>newAliasMap(HashMap::new); aliasMap.put("key1", "value1"); aliasMap.put("key2", Can.ofArray(new String[] {"alias2a", "alias2b"}), "value2"); aliasMap.put("key3", Can.empty(), "value3"); aliasMap.clear(); assertFalse(aliasMap.containsKey("key1")); assertNull(aliasMap.get("key1")); assertFalse(aliasMap.containsKey("key2")); assertNull(aliasMap.get("key2")); assertNull(aliasMap.get("alias2a")); assertNull(aliasMap.get("alias2b")); assertFalse(aliasMap.containsKey("key3")); assertNull(aliasMap.get("key3")); }
@Test void aliasMap_shouldHonorRemoval() { val aliasMap = _Maps.<String, String>newAliasMap(HashMap::new); aliasMap.put("key1", "value1"); aliasMap.put("key2", Can.ofArray(new String[] {"alias2a", "alias2b"}), "value2"); aliasMap.put("key3", Can.empty(), "value3"); aliasMap.remove("key1"); aliasMap.remove("key2"); aliasMap.remove("key3"); assertFalse(aliasMap.containsKey("key1")); assertNull(aliasMap.get("key1")); assertFalse(aliasMap.containsKey("key2")); assertNull(aliasMap.get("key2")); assertNull(aliasMap.get("alias2a")); assertNull(aliasMap.get("alias2b")); assertFalse(aliasMap.containsKey("key3")); assertNull(aliasMap.get("key3")); aliasMap.put("key2", Can.ofArray(new String[] {"alias2a", "alias2b"}), "value2"); }
@Test void aliasMap_shouldThrowOnAliasKeyCollision() { val aliasMap = _Maps.<String, String>newAliasMap(HashMap::new); aliasMap.put("key1", Can.ofArray(new String[] {"alias1a", "alias1b"}), "value1"); assertThrows(IllegalArgumentException.class, ()->{ aliasMap.put("key2", Can.ofArray(new String[] {"alias1a"}), "value2"); }); }