|
|
@@ -8,6 +8,7 @@ package net.ranides.assira.collection.maps;
|
|
|
|
|
|
import java.io.Serializable;
|
|
|
import java.util.*;
|
|
|
+import java.util.AbstractMap.SimpleEntry;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.function.Predicate;
|
|
|
@@ -65,6 +66,79 @@ public final class MapUtils {
|
|
|
return new KeyMapAdapter<>(content, acceptor, function);
|
|
|
}
|
|
|
|
|
|
+ public static <TK, RK, V> Map<RK,V> view(Map<TK, ? extends V> map, Function<TK, RK> keyMapper) {
|
|
|
+ return view(map, keyMapper, Function.identity());
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <TK, RK, TV, RV> Map<RK, RV> view(Map<TK,? extends TV> map, Function<TK, RK> keyMapper, Function<TV, RV> valueMapper) {
|
|
|
+ return new ViewAdapter<>(map, keyMapper, valueMapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class ViewAdapter<TK, RK, TV, RV> extends AMap<RK, RV> {
|
|
|
+
|
|
|
+ private final Map<TK,? extends TV> content;
|
|
|
+
|
|
|
+ private final Function<TK, RK> kmap;
|
|
|
+
|
|
|
+ private final Function<TV, RV> vmap;
|
|
|
+
|
|
|
+ public ViewAdapter(Map<TK,? extends TV> content, Function<TK, RK> kmap, Function<TV, RV> vmap) {
|
|
|
+ this.content = content;
|
|
|
+ this.kmap = kmap;
|
|
|
+ this.vmap = vmap;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return content.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public boolean containsKey(Object key) {
|
|
|
+ try {
|
|
|
+ return content.containsKey(kmap.apply((TK) key));
|
|
|
+ } catch (ClassCastException e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public RV get(Object key) {
|
|
|
+ try {
|
|
|
+ return vmap.apply(content.get(kmap.apply((TK) key)));
|
|
|
+ } catch (ClassCastException e) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ @Override
|
|
|
+ public boolean containsValue(Object value) {
|
|
|
+ try {
|
|
|
+ return content.containsValue(vmap.apply((TV) value));
|
|
|
+ } catch (ClassCastException e) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Set<RK> keySet() {
|
|
|
+ return SetUtils.map(content.keySet(), kmap);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Collection<RV> values() {
|
|
|
+ return CollectionUtils.map(content.values(), vmap);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Set<Entry<RK, RV>> entrySet() {
|
|
|
+ return SetUtils.map(content.entrySet(), e -> new SimpleEntry<>(kmap.apply(e.getKey()), vmap.apply(e.getValue())));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static class MMapAdapter<K, TV, RV> extends MapAdapter<K, TV, RV> implements MultiMap<K, RV> {
|
|
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
@@ -560,7 +634,7 @@ public final class MapUtils {
|
|
|
private Entry<K, V> $toSimpleEntry(Entry<?,?> entry) {
|
|
|
K k = (K)entry.getKey();
|
|
|
V v = (V)entry.getValue();
|
|
|
- return new AbstractMap.SimpleEntry<>(k, v);
|
|
|
+ return new SimpleEntry<>(k, v);
|
|
|
}
|
|
|
|
|
|
private final class KeyMapEntrySet extends ACollection<Entry<K, V>> implements Set<Map.Entry<K, V>>, Serializable {
|