|
|
@@ -6,9 +6,11 @@
|
|
|
*/
|
|
|
package net.ranides.assira.collection.maps;
|
|
|
|
|
|
+import java.io.Serializable;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Map;
|
|
|
import java.util.Set;
|
|
|
+import java.util.function.BiFunction;
|
|
|
import java.util.function.Function;
|
|
|
import net.ranides.assira.collection.CollectionUtils;
|
|
|
import net.ranides.assira.collection.sets.IntSet;
|
|
|
@@ -22,28 +24,59 @@ import net.ranides.assira.generic.CompareUtils;
|
|
|
*/
|
|
|
public final class IntMapUtils {
|
|
|
|
|
|
- // @todo (assira #6) IntMapUtils: multimap, inserter
|
|
|
-
|
|
|
private IntMapUtils() {
|
|
|
/* utility class */
|
|
|
}
|
|
|
|
|
|
public static <TV, RV> IntMap<RV> map(IntMap<TV> map, Function<? super TV, ? extends RV> function) {
|
|
|
- return new MapAdapter<>(map, function);
|
|
|
+ return new MapAdapter<>(map, function, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <TV, RV> IntMap<RV> map(IntMap<TV> map, Function<? super TV, ? extends RV> function, BiFunction<Integer, ? super RV, ? extends RV> inserter) {
|
|
|
+ return new MapAdapter<>(map, function, inserter);
|
|
|
}
|
|
|
|
|
|
public static <TV, RV> IntMap<RV> map(IntMap<TV> map, ProjectionFunction<TV, RV> function) {
|
|
|
return new MapProjection<>(map, function);
|
|
|
}
|
|
|
|
|
|
+ public static <TV, RV> IntMultiMap<RV> map(IntMultiMap<TV> map, Function<? super TV, ? extends RV> function) {
|
|
|
+ return new MMapAdapter<>(map, function, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <TV, RV> IntMultiMap<RV> map(IntMultiMap<TV> map, Function<? super TV, ? extends RV> function, BiFunction<Integer, ? super RV, ? extends RV> inserter) {
|
|
|
+ return new MMapAdapter<>(map, function, inserter);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <TV, RV> IntMultiMap<RV> map(IntMultiMap<TV> map, ProjectionFunction<TV, RV> function) {
|
|
|
+ return new MMapProjection<>(map, function);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <TV, RV> IntMap<RV> wrap(IntMap<TV> map, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
|
+ return new MapWrapper<>(map, getter, setter);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static <K, TV, RV> IntMultiMap<RV> wrap(IntMultiMap<TV> map, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
|
+ return new MMapWrapper<>(map, getter, setter);
|
|
|
+ }
|
|
|
+
|
|
|
private static class MapAdapter<TV, RV> extends AIntMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ private static final BiFunction NSE = (Serializable & BiFunction)(a,b) -> {
|
|
|
+ throw new UnsupportedOperationException();
|
|
|
+ };
|
|
|
|
|
|
- private final IntMap<TV> content;
|
|
|
- private final Function<? super TV, ? extends RV> function;
|
|
|
+ protected final IntMap<TV> content;
|
|
|
+ protected final Function<? super TV, ? extends RV> function;
|
|
|
+ protected final BiFunction<Integer, ? super RV, ? extends RV> inserter;
|
|
|
|
|
|
- public MapAdapter(IntMap<TV> content, Function<? super TV, ? extends RV> function) {
|
|
|
+ public MapAdapter(IntMap<TV> content, Function<? super TV, ? extends RV> function, BiFunction<Integer, ? super RV, ? extends RV> inserter) {
|
|
|
this.content = content;
|
|
|
this.function = function;
|
|
|
+ this.inserter = null != inserter ? inserter : NSE;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -91,6 +124,12 @@ public final class IntMapUtils {
|
|
|
public RV get(int key) {
|
|
|
return function.apply(content.get(key));
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RV put(int key, RV value) {
|
|
|
+ return inserter.apply(key, value);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
private final class EntryAdapter implements IntEntry<RV> {
|
|
|
|
|
|
@@ -112,7 +151,7 @@ public final class IntMapUtils {
|
|
|
|
|
|
@Override
|
|
|
public RV setValue(RV value) {
|
|
|
- throw new UnsupportedOperationException();
|
|
|
+ return inserter.apply(delegate.getKey(), value);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -143,10 +182,12 @@ public final class IntMapUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
- private static class MapProjection<K, TV, RV> extends AIntMap<RV> {
|
|
|
+ private static class MapProjection<TV, RV> extends AIntMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
|
|
|
- private final IntMap<TV> content;
|
|
|
- private final ProjectionFunction<TV, RV> function;
|
|
|
+ protected final IntMap<TV> content;
|
|
|
+ protected final ProjectionFunction<TV, RV> function;
|
|
|
|
|
|
public MapProjection(IntMap<TV> content, ProjectionFunction<TV, RV> function) {
|
|
|
this.content = content;
|
|
|
@@ -261,11 +302,11 @@ public final class IntMapUtils {
|
|
|
}
|
|
|
if (getClass() == obj.getClass()) {
|
|
|
@SuppressWarnings("unchecked")
|
|
|
- MapProjection.EntryProjection other = (MapProjection.EntryProjection) obj;
|
|
|
+ EntryProjection other = (EntryProjection) obj;
|
|
|
return delegate.equals(other.delegate);
|
|
|
} else {
|
|
|
@SuppressWarnings("unchecked")
|
|
|
- Map.Entry<K,RV> other = (Map.Entry<K,RV>)obj;
|
|
|
+ Map.Entry<Integer,RV> other = (Map.Entry<Integer,RV>)obj;
|
|
|
return CompareUtils.equals(getKey(), other.getKey()) && CompareUtils.equals(getValue(), other.getValue());
|
|
|
}
|
|
|
}
|
|
|
@@ -274,4 +315,160 @@ public final class IntMapUtils {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ private static class MMapAdapter<TV, RV> extends MapAdapter<TV, RV> implements IntMultiMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ private final IntMultiMap<TV> mcontent;
|
|
|
+
|
|
|
+ public MMapAdapter(IntMultiMap<TV> mcontent, Function<? super TV, ? extends RV> function, BiFunction<Integer, ? super RV, ? extends RV> setter) {
|
|
|
+ super(mcontent, function, setter);
|
|
|
+ this.mcontent = mcontent;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Collection<RV> getAll(int key) {
|
|
|
+ return CollectionUtils.map(mcontent.getAll(key), function);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class MMapProjection<TV, RV> extends MapProjection<TV,RV> implements IntMultiMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ private final IntMultiMap<TV> mcontent;
|
|
|
+
|
|
|
+ public MMapProjection(IntMultiMap<TV> content, ProjectionFunction<TV, RV> function) {
|
|
|
+ super(content, function);
|
|
|
+ this.mcontent = content;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Collection<RV> getAll(int key) {
|
|
|
+ return CollectionUtils.map(mcontent.getAll(key), function);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class MMapWrapper<TV, RV> extends MapWrapper<TV,RV> implements IntMultiMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ private final IntMultiMap<TV> mcontent;
|
|
|
+
|
|
|
+ public MMapWrapper(IntMultiMap<TV> content, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
|
+ super(content, getter, setter);
|
|
|
+ this.mcontent = content;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Collection<RV> getAll(int key) {
|
|
|
+ return CollectionUtils.map(mcontent.getAll(key), getter);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private static class MapWrapper<TV, RV> extends AIntMap<RV> implements IntMap<RV> {
|
|
|
+
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
+
|
|
|
+ protected final IntMap<TV> content;
|
|
|
+ protected final Function<? super TV, ? extends RV> getter;
|
|
|
+ protected final BiFunction<? super TV, ? super RV, ? extends RV> setter;
|
|
|
+
|
|
|
+ public MapWrapper(IntMap<TV> content, Function<? super TV, ? extends RV> getter, BiFunction<? super TV, ? super RV, ? extends RV> setter) {
|
|
|
+ this.content = content;
|
|
|
+ this.getter = getter;
|
|
|
+ this.setter = setter;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int size() {
|
|
|
+ return content.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean containsKey(int key) {
|
|
|
+ return content.containsKey(key);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean containsValue(Object value) {
|
|
|
+ return values().contains(value);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RV get(int key) {
|
|
|
+ TV var = content.get(key);
|
|
|
+ return null!=var ? getter.apply(var) : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RV put(int key, RV value) {
|
|
|
+ TV var = content.get(key);
|
|
|
+ return null!=var ? setter.apply(var, value) : null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IntSet keySet() {
|
|
|
+ return content.keySet();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Collection<RV> values() {
|
|
|
+ return CollectionUtils.map(content.values(), getter);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Set<IntEntry<RV>> fastEntrySet() {
|
|
|
+ return SetUtils.map(content.fastEntrySet(), e -> new EntryWrapper(e));
|
|
|
+ }
|
|
|
+
|
|
|
+ private final class EntryWrapper implements IntEntry<RV> {
|
|
|
+
|
|
|
+ private final IntEntry<TV> delegate;
|
|
|
+
|
|
|
+ public EntryWrapper(IntEntry<TV> delegate) {
|
|
|
+ this.delegate = delegate;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int getIntKey() {
|
|
|
+ return delegate.getKey();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RV getValue() {
|
|
|
+ return getter.apply(delegate.getValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RV setValue(RV value) {
|
|
|
+ return setter.apply(delegate.getValue(), value);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ return delegate.hashCode();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object obj) {
|
|
|
+ if (this == obj) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (!(obj instanceof Map.Entry)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Map.Entry<Integer,RV> other = (Map.Entry<Integer,RV>)obj;
|
|
|
+ return CompareUtils.equals(getKey(), other.getKey())
|
|
|
+ && CompareUtils.equals(getValue(), other.getValue());
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|