diff options
| author | Ben Culkin <scorpress@gmail.com> | 2022-09-24 12:34:49 -0400 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2022-09-24 12:34:49 -0400 |
| commit | a7ab5364c4fc372d70ef5df910d38feec6be3adb (patch) | |
| tree | d99766c23fd4ae7e9cd1833df2d13d244aab4575 | |
| parent | f7d96d88798c904f69f0b5306a5ddecd0456b377 (diff) | |
Add PairMap
| -rw-r--r-- | src/main/java/bjc/esodata/PairMap.java | 145 |
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(); + } + +} |
