|
@@ -7,12 +7,13 @@
|
|
|
package net.ranides.assira.collection.maps;
|
|
package net.ranides.assira.collection.maps;
|
|
|
|
|
|
|
|
import java.io.Serializable;
|
|
import java.io.Serializable;
|
|
|
-import java.util.Collection;
|
|
|
|
|
-import java.util.Collections;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.Set;
|
|
|
|
|
|
|
+import java.util.*;
|
|
|
import java.util.function.BiFunction;
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.Function;
|
|
import java.util.function.Function;
|
|
|
|
|
+import java.util.function.Predicate;
|
|
|
|
|
+import java.util.function.Supplier;
|
|
|
|
|
+
|
|
|
|
|
+import net.ranides.assira.collection.ACollection;
|
|
|
import net.ranides.assira.collection.CollectionUtils;
|
|
import net.ranides.assira.collection.CollectionUtils;
|
|
|
import net.ranides.assira.collection.sets.SetUtils;
|
|
import net.ranides.assira.collection.sets.SetUtils;
|
|
|
import net.ranides.assira.functional.ProjectionFunction;
|
|
import net.ranides.assira.functional.ProjectionFunction;
|
|
@@ -59,7 +60,11 @@ public final class MapUtils {
|
|
|
public static <K, TV, RV> MultiMap<K,RV> wrap(MultiMap<K,TV> map, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
public static <K, TV, RV> MultiMap<K,RV> wrap(MultiMap<K,TV> map, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
|
return new MMapWrapper<>(map, getter, setter);
|
|
return new MMapWrapper<>(map, getter, setter);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ public static <K,V> Map<K,V> keyproxy(Supplier<Map<K, V>> content, Predicate<Object> acceptor, Function<K, K> function) {
|
|
|
|
|
+ return new KeyMapAdapter<>(content, acceptor, function);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private static class MMapAdapter<K, TV, RV> extends MapAdapter<K, TV, RV> implements MultiMap<K, RV> {
|
|
private static class MMapAdapter<K, TV, RV> extends MapAdapter<K, TV, RV> implements MultiMap<K, RV> {
|
|
|
|
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
private static final long serialVersionUID = 1L;
|
|
@@ -444,5 +449,161 @@ public final class MapUtils {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ private static class KeyMapAdapter<K, V> extends AMap<K, V> {
|
|
|
|
|
+
|
|
|
|
|
+ protected final Map<K, V> content;
|
|
|
|
|
+ protected final Predicate<Object> acceptor;
|
|
|
|
|
+ protected final Function<K, K> function;
|
|
|
|
|
+
|
|
|
|
|
+ KeyMapAdapter(Supplier<Map<K, V>> content, Predicate<Object> acceptor, Function<K, K> function) {
|
|
|
|
|
+ this.content = content.get();
|
|
|
|
|
+ this.acceptor = acceptor;
|
|
|
|
|
+ this.function = function;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Set<Entry<K, V>> entrySet() {
|
|
|
|
|
+ return new KeyMapEntrySet();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int size() {
|
|
|
|
|
+ return content.size();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean containsValue(Object value) {
|
|
|
|
|
+ return content.containsValue(value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V get(Object key) {
|
|
|
|
|
+ return acceptor.test(key) ? content.get(asKey(key)) : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V getOrDefault(Object key, V defaultValue) {
|
|
|
|
|
+ return acceptor.test(key) ? content.getOrDefault(asKey(key), defaultValue) : defaultValue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean containsKey(Object key) {
|
|
|
|
|
+ return acceptor.test(key) ? content.containsKey(asKey(key)) : false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V put(K key, V value) {
|
|
|
|
|
+ return content.put(asKey(key), value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void putAll(Map<? extends K, ? extends V> m) {
|
|
|
|
|
+ for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
|
|
|
|
|
+ K key = e.getKey();
|
|
|
|
|
+ V value = e.getValue();
|
|
|
|
|
+ content.put(asKey(key), value);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V remove(Object key) {
|
|
|
|
|
+ return acceptor.test(key) ? content.remove(asKey(key)) : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V putIfAbsent(K key, V value) {
|
|
|
|
|
+ return content.putIfAbsent(asKey(key), value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean remove(Object key, Object value) {
|
|
|
|
|
+ return acceptor.test(key) && content.remove(asKey(key), value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean replace(K key, V oldValue, V newValue) {
|
|
|
|
|
+ return content.replace(asKey(key), oldValue, newValue);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V replace(K key, V value) {
|
|
|
|
|
+ return content.replace(asKey(key), value);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
|
|
|
|
|
+ return content.computeIfAbsent(asKey(key), mappingFunction);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
|
|
|
|
+ return content.computeIfPresent(asKey(key), remappingFunction);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
|
|
|
|
+ return content.compute(asKey(key), remappingFunction);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
|
|
|
|
+ return content.merge(asKey(key), value, remappingFunction);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private K asKey(Object key) {
|
|
|
|
|
+ return key!=null ? function.apply((K)key) : null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private Entry<K, V> asEntry(Entry<K, V> entry) {
|
|
|
|
|
+ K k = asKey(entry.getKey());
|
|
|
|
|
+ V v = entry.getValue();
|
|
|
|
|
+ return new AbstractMap.SimpleEntry<>(k, v);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private final class KeyMapEntrySet extends ACollection<Entry<K, V>> implements Set<Map.Entry<K, V>>, Serializable {
|
|
|
|
|
+
|
|
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
|
|
+
|
|
|
|
|
+ private final Set<Entry<K, V>> entries = content.entrySet();
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean contains(Object o) {
|
|
|
|
|
+ return o instanceof Entry<?,?> && entries.contains(asEntry((Entry<K, V>) o));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean add(Entry<K, V> kvEntry) {
|
|
|
|
|
+ return entries.add(asEntry(kvEntry));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Iterator<Map.Entry<K, V>> iterator() {
|
|
|
|
|
+ return entries.iterator();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int size() {
|
|
|
|
|
+ return entries.size();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int hashCode() {
|
|
|
|
|
+ return entries.hashCode();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean equals(Object obj) {
|
|
|
|
|
+ if(obj instanceof Set) {
|
|
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
|
|
+ Set<Entry<K, V>> that = (Set<Entry<K, V>>)obj;
|
|
|
|
|
+ return this.size() == that.size() && this.containsAll(that);
|
|
|
|
|
+ }
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
}
|
|
}
|