|
|
@@ -1,211 +1,180 @@
|
|
|
-/*
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
- * @copyright Ranides Atterwim
|
|
|
- * @license WTFPL
|
|
|
- * @url http://ranides.net/projects/assira
|
|
|
- */
|
|
|
-package net.ranides.assira.collections.map;
|
|
|
-
|
|
|
-import java.util.Collection;
|
|
|
-import java.util.ConcurrentModificationException;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Map.Entry;
|
|
|
-import java.util.Objects;
|
|
|
-import java.util.Set;
|
|
|
-import java.util.function.BiConsumer;
|
|
|
-import java.util.function.BiFunction;
|
|
|
-import java.util.function.Function;
|
|
|
-
|
|
|
-/**
|
|
|
- *
|
|
|
- * @author msieron
|
|
|
- */
|
|
|
-
|
|
|
-
|
|
|
-public interface GenericMap<K> {
|
|
|
-
|
|
|
- int size();
|
|
|
-
|
|
|
- boolean isEmpty();
|
|
|
-
|
|
|
- boolean containsKey(GenericKey<K,?> key);
|
|
|
-
|
|
|
- boolean containsValue(Object value);
|
|
|
-
|
|
|
- <V> V get(GenericKey<K,V> key);
|
|
|
-
|
|
|
- <V> V put(GenericKey<K,V> key, V value);
|
|
|
-
|
|
|
- <V> V remove(GenericKey<K,V> key);
|
|
|
-
|
|
|
-
|
|
|
- void putAll(GenericMap<? extends K> m);
|
|
|
-
|
|
|
- void clear();
|
|
|
-
|
|
|
- Set<GenericKey<K,?>> keySet();
|
|
|
-
|
|
|
- Collection<?> values();
|
|
|
-
|
|
|
- Set<Map.Entry<GenericKey<K,?>, ?>> entrySet();
|
|
|
-
|
|
|
- boolean equals(Object o);
|
|
|
-
|
|
|
- int hashCode();
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- default <V> V getOrDefault(GenericKey<K,V> key, V defaultValue) {
|
|
|
- V v;
|
|
|
- return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue;
|
|
|
- }
|
|
|
-
|
|
|
- default void forEach(BiConsumer<? super GenericKey<K,?>, Object> action) {
|
|
|
- Objects.requireNonNull(action);
|
|
|
- for (Map.Entry<GenericKey<K,?>, ?> entry : entrySet()) {
|
|
|
- GenericKey<K,?> k;
|
|
|
- Object v;
|
|
|
- try {
|
|
|
- k = entry.getKey();
|
|
|
- v = entry.getValue();
|
|
|
- } catch(IllegalStateException ise) {
|
|
|
- // this usually means the entry is no longer in the map.
|
|
|
- throw new ConcurrentModificationException(ise);
|
|
|
- }
|
|
|
- action.accept(k, v);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- default void replaceAll(BiFunction<? super GenericKey<K,?>, Object, Object> function) {
|
|
|
- Objects.requireNonNull(function);
|
|
|
- for (Map.Entry<GenericKey<K,?>, ?> entry : entrySet()) {
|
|
|
- GenericKey<K,?> k;
|
|
|
- Object v;
|
|
|
- try {
|
|
|
- k = entry.getKey();
|
|
|
- v = entry.getValue();
|
|
|
- } catch(IllegalStateException ise) {
|
|
|
- // this usually means the entry is no longer in the map.
|
|
|
- throw new ConcurrentModificationException(ise);
|
|
|
- }
|
|
|
-
|
|
|
- // ise thrown from function is not a cme.
|
|
|
- v = function.apply(k, v);
|
|
|
-
|
|
|
- try {
|
|
|
- ((Entry)entry).setValue(v);
|
|
|
- } catch(IllegalStateException ise) {
|
|
|
- // this usually means the entry is no longer in the map.
|
|
|
- throw new ConcurrentModificationException(ise);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V putIfAbsent(GenericKey<K,V> key, V value) {
|
|
|
- V v = get(key);
|
|
|
- if (v == null) {
|
|
|
- v = put(key, value);
|
|
|
- }
|
|
|
-
|
|
|
- return v;
|
|
|
- }
|
|
|
-
|
|
|
- default <V> boolean remove(GenericKey<K,V> key, V value) {
|
|
|
- Object curValue = get(key);
|
|
|
- if (!Objects.equals(curValue, value) ||
|
|
|
- (curValue == null && !containsKey(key))) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- remove(key);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- default <V> boolean replace(GenericKey<K,V> key, V oldValue, V newValue) {
|
|
|
- Object curValue = get(key);
|
|
|
- if (!Objects.equals(curValue, oldValue) ||
|
|
|
- (curValue == null && !containsKey(key))) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- put(key, newValue);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V replace(GenericKey<K,V> key, V value) {
|
|
|
- V curValue;
|
|
|
- if (((curValue = get(key)) != null) || containsKey(key)) {
|
|
|
- curValue = put(key, value);
|
|
|
- }
|
|
|
- return curValue;
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V computeIfAbsent(GenericKey<K,V> key,
|
|
|
- Function<? super GenericKey<K,V>, ? extends V> mappingFunction) {
|
|
|
- Objects.requireNonNull(mappingFunction);
|
|
|
- V v;
|
|
|
- if ((v = get(key)) == null) {
|
|
|
- V newValue;
|
|
|
- if ((newValue = mappingFunction.apply(key)) != null) {
|
|
|
- put(key, newValue);
|
|
|
- return newValue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return v;
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V computeIfPresent(GenericKey<K,V> key,
|
|
|
- BiFunction<? super GenericKey<K,?>, ? super V, ? extends V> remappingFunction) {
|
|
|
- Objects.requireNonNull(remappingFunction);
|
|
|
- V oldValue;
|
|
|
- if ((oldValue = get(key)) != null) {
|
|
|
- V newValue = remappingFunction.apply(key, oldValue);
|
|
|
- if (newValue != null) {
|
|
|
- put(key, newValue);
|
|
|
- return newValue;
|
|
|
- } else {
|
|
|
- remove(key);
|
|
|
- return null;
|
|
|
- }
|
|
|
- } else {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V compute(GenericKey<K,V> key,
|
|
|
- BiFunction<? super GenericKey<K,V>, ? super V, ? extends V> remappingFunction) {
|
|
|
- Objects.requireNonNull(remappingFunction);
|
|
|
- V oldValue = get(key);
|
|
|
-
|
|
|
- V newValue = remappingFunction.apply(key, oldValue);
|
|
|
- if (newValue == null) {
|
|
|
- // delete mapping
|
|
|
- if (oldValue != null || containsKey(key)) {
|
|
|
- // something to remove
|
|
|
- remove(key);
|
|
|
- return null;
|
|
|
- } else {
|
|
|
- // nothing to do. Leave things as they were.
|
|
|
- return null;
|
|
|
- }
|
|
|
- } else {
|
|
|
- // add or replace old mapping
|
|
|
- put(key, newValue);
|
|
|
- return newValue;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- default <V> V merge(GenericKey<K,V> key, V value,
|
|
|
- BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
|
|
- Objects.requireNonNull(remappingFunction);
|
|
|
- Objects.requireNonNull(value);
|
|
|
- V oldValue = get(key);
|
|
|
- V newValue = (oldValue == null) ? value :
|
|
|
- remappingFunction.apply(oldValue, value);
|
|
|
- if(newValue == null) {
|
|
|
- remove(key);
|
|
|
- } else {
|
|
|
- put(key, newValue);
|
|
|
- }
|
|
|
- return newValue;
|
|
|
- }
|
|
|
-}
|
|
|
+/*
|
|
|
+ * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
+ * @copyright Ranides Atterwim
|
|
|
+ * @license WTFPL
|
|
|
+ * @url http://ranides.net/projects/assira
|
|
|
+ */
|
|
|
+package net.ranides.assira.collections.map;
|
|
|
+
|
|
|
+import java.util.Collection;
|
|
|
+import java.util.ConcurrentModificationException;
|
|
|
+import java.util.Objects;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.function.BiConsumer;
|
|
|
+import java.util.function.BiFunction;
|
|
|
+import java.util.function.Function;
|
|
|
+
|
|
|
+/**
|
|
|
+ *
|
|
|
+ * @author msieron
|
|
|
+ */
|
|
|
+public interface GenericMap<K> {
|
|
|
+
|
|
|
+ int size();
|
|
|
+
|
|
|
+ boolean isEmpty();
|
|
|
+
|
|
|
+ boolean containsKey(GenericKey<K,?> key);
|
|
|
+
|
|
|
+ boolean containsValue(Object value);
|
|
|
+
|
|
|
+ <V> V get(GenericKey<K,V> key);
|
|
|
+
|
|
|
+ <V> V put(GenericKey<K,V> key, V value);
|
|
|
+
|
|
|
+ default <V> V put(GenericKey<K,V> key, Optional<V> value) {
|
|
|
+ if(value.isPresent()) {
|
|
|
+ return put(key, value.get());
|
|
|
+ } else {
|
|
|
+ return get(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ <V> V remove(GenericKey<K,V> key);
|
|
|
+
|
|
|
+ void putAll(GenericMap<? extends K> m);
|
|
|
+
|
|
|
+ void clear();
|
|
|
+
|
|
|
+ Set<GenericKey<K,?>> keySet();
|
|
|
+
|
|
|
+ Collection<?> values();
|
|
|
+
|
|
|
+ Set<GenericEntry<K>> entrySet();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ boolean equals(Object o);
|
|
|
+
|
|
|
+ @Override
|
|
|
+ int hashCode();
|
|
|
+
|
|
|
+ default <V> V getOrDefault(GenericKey<K,V> key, V ddefault) {
|
|
|
+ V v;
|
|
|
+ return (((v = get(key)) != null) || containsKey(key)) ? v : ddefault;
|
|
|
+ }
|
|
|
+
|
|
|
+ default void forEach(BiConsumer<? super GenericKey<K,?>, Object> action) {
|
|
|
+ Objects.requireNonNull(action);
|
|
|
+ for (GenericEntry<K> entry : entrySet()) {
|
|
|
+ GenericKey<K,?> k;
|
|
|
+ Object v;
|
|
|
+ try {
|
|
|
+ k = entry.getKey();
|
|
|
+ v = entry.getValue();
|
|
|
+ } catch(IllegalStateException ise) {
|
|
|
+ // this usually means the entry is no longer in the map.
|
|
|
+ throw new ConcurrentModificationException(ise);
|
|
|
+ }
|
|
|
+ action.accept(k, v);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ default void replaceAll(BiFunction<? super GenericKey<K,?>, Object, Object> function) {
|
|
|
+ Objects.requireNonNull(function);
|
|
|
+ for (GenericEntry<K> entry : entrySet()) {
|
|
|
+ GenericKey<K,?> k;
|
|
|
+ Object v;
|
|
|
+ try {
|
|
|
+ k = entry.getKey();
|
|
|
+ v = entry.getValue();
|
|
|
+ } catch(IllegalStateException ise) {
|
|
|
+ // this usually means the entry is no longer in the map.
|
|
|
+ throw new ConcurrentModificationException(ise);
|
|
|
+ }
|
|
|
+
|
|
|
+ // ise thrown from function is not a cme.
|
|
|
+ v = function.apply(k, v);
|
|
|
+
|
|
|
+ try {
|
|
|
+ entry.setValue(k.type().cast(v));
|
|
|
+ } catch(IllegalStateException ise) {
|
|
|
+ // this usually means the entry is no longer in the map.
|
|
|
+ throw new ConcurrentModificationException(ise);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V putIfAbsent(GenericKey<K,V> key, V value) {
|
|
|
+ V v = get(key);
|
|
|
+ if (v == null) {
|
|
|
+ v = put(key, value);
|
|
|
+ }
|
|
|
+
|
|
|
+ return v;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> boolean remove(GenericKey<K,V> key, V value) {
|
|
|
+ Object current = get(key);
|
|
|
+ if (!Objects.equals(current, value) || (current == null && !containsKey(key))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ remove(key);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> boolean replace(GenericKey<K,V> key, V oldValue, V value) {
|
|
|
+ Object current = get(key);
|
|
|
+ if (!Objects.equals(current, oldValue) || (current == null && !containsKey(key))) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ put(key, value);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V replace(GenericKey<K,V> key, V value) {
|
|
|
+ V current;
|
|
|
+ if (((current = get(key)) != null) || containsKey(key)) {
|
|
|
+ current = put(key, value);
|
|
|
+ }
|
|
|
+ return current;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V computeIfAbsent(GenericKey<K,V> key, Function<? super GenericKey<K,V>, ? extends V> function) {
|
|
|
+ Objects.requireNonNull(function);
|
|
|
+ V prev;
|
|
|
+ if (null == (prev = get(key)) && !containsKey(key)) {
|
|
|
+ V value = function.apply(key);
|
|
|
+ put(key, value);
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+ return prev;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V computeIfPresent(GenericKey<K,V> key, BiFunction<? super GenericKey<K,?>, ? super V, ? extends V> function) {
|
|
|
+ Objects.requireNonNull(function);
|
|
|
+ V prev;
|
|
|
+ if (null != (prev = get(key)) || containsKey(key)) {
|
|
|
+ V value = function.apply(key, prev);
|
|
|
+ put(key, value);
|
|
|
+ return value;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V compute(GenericKey<K,V> key, BiFunction<? super GenericKey<K,V>, ? super V, ? extends V> function) {
|
|
|
+ Objects.requireNonNull(function);
|
|
|
+ V value = function.apply(key, get(key));
|
|
|
+ put(key, value);
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+
|
|
|
+ default <V> V merge(GenericKey<K,V> key, V value, BiFunction<? super V, ? super V, ? extends V> function) {
|
|
|
+ Objects.requireNonNull(function);
|
|
|
+ V prev = get(key);
|
|
|
+ V newValue = (prev == null) ? value : function.apply(prev, value);
|
|
|
+ put(key, newValue);
|
|
|
+ return newValue;
|
|
|
+ }
|
|
|
+}
|