summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Culkin <scorpress@gmail.com>2022-09-24 12:34:49 -0400
committerBen Culkin <scorpress@gmail.com>2022-09-24 12:34:49 -0400
commita7ab5364c4fc372d70ef5df910d38feec6be3adb (patch)
treed99766c23fd4ae7e9cd1833df2d13d244aab4575
parentf7d96d88798c904f69f0b5306a5ddecd0456b377 (diff)
Add PairMap
-rw-r--r--src/main/java/bjc/esodata/PairMap.java145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/main/java/bjc/esodata/PairMap.java b/src/main/java/bjc/esodata/PairMap.java
new file mode 100644
index 0000000..ba13a2f
--- /dev/null
+++ b/src/main/java/bjc/esodata/PairMap.java
@@ -0,0 +1,145 @@
+package bjc.esodata;
+
+import java.util.*;
+
+import bjc.data.Pair;
+
+/**
+ * Represents a map keyed by pairs, where you can look up all the items that
+ * have a particular left or right key value.
+ *
+ * NOTE: Using the keySet/values/entrySet views to modify the map will break the
+ * tracking invariants.
+ *
+ * @author bjcul
+ *
+ * @param <Left>
+ * @param <Right>
+ * @param <Value>
+ */
+public class PairMap<Left, Right, Value> implements Map<Pair<Left, Right>, Value> {
+ private Map<Pair<Left, Right>, Value> backing;
+
+ private Multimap<Left, Pair<Left, Right>> leftTracker;
+ private Multimap<Right, Pair<Left, Right>> rightTracker;
+
+ /**
+ * Create a new pair map.
+ */
+ public PairMap() {
+ this.backing = new HashMap<>();
+
+ this.leftTracker = new Multimap<>();
+ this.rightTracker = new Multimap<>();
+ }
+
+ /**
+ * Get all of the key-pairs which contain the given left value.
+ *
+ * @param val The value to search for.
+ *
+ * @return All of the key-pairs containing the given value.
+ */
+ public Set<Pair<Left, Right>> getLeft(Left val) {
+ return leftTracker.get(val);
+ }
+
+ /**
+ * Get all of the key-pairs which contain the given right value.
+ *
+ * @param val The value to search for.
+ *
+ * @return All of the key-pairs containing the given value.
+ */
+ public Set<Pair<Left, Right>> getRight(Right val) {
+ return rightTracker.get(val);
+ }
+
+ /**
+ * Get a value without having to construct a pair callee-side
+ *
+ * @param lft The left value
+ * @param rght The right value.
+ *
+ * @return The value corresponding to the given key-pair, if one exists
+ */
+ public Value biget(Left lft, Right rght) {
+ return backing.get(Pair.pair(lft, rght));
+ }
+
+ @Override
+ public int size() {
+ return backing.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return backing.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return backing.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return backing.containsKey(value);
+ }
+
+ @Override
+ public Value get(Object key) {
+ return backing.get(key);
+ }
+
+ @Override
+ public Value put(Pair<Left, Right> key, Value value) {
+ Value ret = backing.put(key, value);
+ leftTracker.add(key.getLeft(), key);
+ rightTracker.add(key.getRight(), key);
+ return ret;
+ }
+
+ @Override
+ public Value remove(Object key) {
+ @SuppressWarnings("unchecked")
+ Pair<Left, Right> actKey = (Pair<Left, Right>) key;
+
+ leftTracker.remove(actKey.getLeft(), actKey);
+ rightTracker.remove(actKey.getRight(), actKey);
+
+ return backing.remove(key);
+ }
+
+ @Override
+ public void putAll(Map<? extends Pair<Left, Right>, ? extends Value> m) {
+ for (Entry<? extends Pair<Left, Right>, ? extends Value> entry : m.entrySet()) {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public void clear() {
+ backing.clear();
+
+ leftTracker = new Multimap<>();
+ rightTracker = new Multimap<>();
+ }
+
+ // TODO: Update these to not break the tracking invariants
+ @Override
+ public Set<Pair<Left, Right>> keySet() {
+ return backing.keySet();
+ }
+
+ @Override
+ public Collection<Value> values() {
+ return backing.values();
+ }
+
+ @Override
+ public Set<Entry<Pair<Left, Right>, Value>> entrySet() {
+ return backing.entrySet();
+ }
+
+}