summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorbculkin2442 <bjculkin@mix.wvu.edu>2019-07-27 23:10:16 -0400
committerbculkin2442 <bjculkin@mix.wvu.edu>2019-07-27 23:10:16 -0400
commitfadc9d01f662ab001d9fdd0fd92c5f0c177557cd (patch)
tree0747e6746c3b7f33016bf8ed0324bd6972b09795 /src/main/java
parenta623c8fafaa103a902fbdb4936b2ee78463ae5ba (diff)
Reimplement AbbrevMap, and implement Multimap
This reimplements the old AbbrevMap structure as AbbrevMap2, and created a new Multimap structure as a apart of it. Multimap is exactly what it sounds like; a map that allows multiple values for a given key. The only real thing that is different about it, is that if you add a key-value pair multiple times, you'll have to remove it multiple times.
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/bjc/esodata/AbbrevMap.java206
-rw-r--r--src/main/java/bjc/esodata/AbbrevMap2.java93
-rw-r--r--src/main/java/bjc/esodata/Multimap.java110
-rw-r--r--src/main/java/bjc/esodata/ThresholdSet.java27
4 files changed, 226 insertions, 210 deletions
diff --git a/src/main/java/bjc/esodata/AbbrevMap.java b/src/main/java/bjc/esodata/AbbrevMap.java
deleted file mode 100644
index 51ec5c0..0000000
--- a/src/main/java/bjc/esodata/AbbrevMap.java
+++ /dev/null
@@ -1,206 +0,0 @@
-package bjc.esodata;
-
-import java.util.*;
-
-import bjc.funcdata.*;
-
-/*
- * Represents a mapping from a set of strings to a mapping of all unambiguous
- * prefixes of their respective strings.
- *
- * This works the same as Ruby's Abbrev module.
- *
- * @author EVE
- */
-//public class AbbrevMap {
-// private ThresholdSet<String> wordSet;
-//
-// /* All of the words we have abbreviations for. */
-// private final Set<String> wrds;
-//
-// /* Maps abbreviations to their strings. */
-// private IMap<String, String> abbrevMap;
-//
-// /* Counts how many times we've seen a substring. */
-// private Set<String> seen;
-//
-// /* Maps ambiguous abbreviations to the strings they could be. */
-// private SetMultimap<String, String> ambMap;
-//
-// /**
-// * Create a new abbreviation map.
-// *
-// * @param words
-// * The initial set of words to put in the map.
-// */
-// public AbbrevMap(final String... words) {
-// wrds = new HashSet<>(Arrays.asList(words));
-//
-// recalculate();
-// }
-//
-// /**
-// * Recalculate all the abbreviations in this map.
-// *
-// * This may be needed after certain operations to ensure that all of the
-// * results are correct.
-// */
-// public void recalculate() {
-// abbrevMap = new FunctionalMap<>();
-//
-// ambMap = HashMultimap.create();
-//
-// seen = new HashSet<>();
-//
-// for(final String word : wrds) {
-// intAddWord(word);
-// }
-// }
-//
-// /**
-// * Adds words to the abbreviation map.
-// *
-// * @param words
-// * The words to add to the abbreviation map.
-// */
-// public void addWords(final String... words) {
-// wrds.addAll(Arrays.asList(words));
-//
-// for(final String word : words) {
-// intAddWord(word);
-// }
-// }
-//
-// /* Actually add abbreviations of a word. */
-// private void intAddWord(final String word) {
-// /* A word always abbreviates to itself. */
-// abbrevMap.put(word, word);
-//
-// /* Skip blank words. */
-// if(word.equals("")) return;
-//
-// /* Handle each possible abbreviation. */
-// for(int i = word.length(); i > 0; i--) {
-// final String subword = word.substring(0, i);
-//
-// if(seen.contains(subword)) {
-// /*
-// * Remove a mapping if its ambiguous and not a
-// * whole word.
-// */
-// if(abbrevMap.containsKey(subword) && !wrds.contains(subword)) {
-// final String oldword = abbrevMap.remove(subword);
-//
-// ambMap.put(subword, oldword);
-// ambMap.put(subword, word);
-// } else if(!wrds.contains(subword)) {
-// ambMap.put(subword, word);
-// }
-// } else {
-// seen.add(subword);
-//
-// abbrevMap.put(subword, word);
-// }
-// }
-// }
-//
-// /**
-// * Removes words from the abbreviation map.
-// *
-// * NOTE: There may be inconsistent behavior after removing a word from
-// * the map. Use {@link AbbrevMap#recalculate()} to fix it if it occurs.
-// *
-// * @param words
-// * The words to remove.
-// */
-// public void removeWords(final String... words) {
-// wrds.removeAll(Arrays.asList(words));
-//
-// for(final String word : words) {
-// intRemoveWord(word);
-// }
-// }
-//
-// /* Actually remove a word. */
-// private void intRemoveWord(final String word) {
-// /* Skip blank words. */
-// if(word.equals("")) return;
-//
-// /* Handle each possible abbreviation. */
-// for(int i = word.length(); i > 0; i--) {
-// final String subword = word.substring(0, i);
-//
-// if(abbrevMap.containsKey(subword)) {
-// abbrevMap.remove(subword);
-// } else {
-// ambMap.remove(subword, word);
-//
-// final Set<String> possWords = ambMap.get(subword);
-//
-// if(possWords.size() == 0) {
-// seen.remove(subword);
-// } else if(possWords.size() == 1) {
-// /*
-// * An abbreviation went from ambiguous
-// * to non-ambiguous.
-// */
-// final String newWord = possWords.iterator().next();
-//
-// abbrevMap.put(subword, newWord);
-// ambMap.remove(subword, newWord);
-// }
-// }
-// }
-// }
-//
-// /**
-// * Convert an abbreviation into all the strings it could abbreviate
-// * into.
-// *
-// * @param abbrev
-// * The abbreviation to convert.
-// *
-// * @return All the expansions for the provided abbreviation.
-// */
-// public String[] deabbrev(final String abbrev) {
-// if(abbrevMap.containsKey(abbrev)) {
-// return new String[] {
-// abbrevMap.get(abbrev)
-// };
-// }
-//
-// return ambMap.get(abbrev).toArray(new String[0]);
-// }
-//
-// @Override
-// public int hashCode() {
-// final int prime = 31;
-//
-// int result = 1;
-// result = prime * result + (wrds == null ? 0 : wrds.hashCode());
-//
-// return result;
-// }
-//
-// @Override
-// public boolean equals(final Object obj) {
-// if(this == obj) return true;
-// if(obj == null) return false;
-// if(!(obj instanceof AbbrevMap)) return false;
-//
-// final AbbrevMap other = (AbbrevMap) obj;
-//
-// if(wrds == null) {
-// if(other.wrds != null) return false;
-// } else if(!wrds.equals(other.wrds)) return false;
-//
-// return true;
-// }
-//
-// @Override
-// public String toString() {
-// final String fmt = "AbbrevMap [wrds=%s, abbrevMap=%s, seen=%s, ambMap=%s]";
-//
-// return String.format(fmt, wrds, abbrevMap, seen, ambMap);
-// }
-//}
diff --git a/src/main/java/bjc/esodata/AbbrevMap2.java b/src/main/java/bjc/esodata/AbbrevMap2.java
new file mode 100644
index 0000000..f79a2d2
--- /dev/null
+++ b/src/main/java/bjc/esodata/AbbrevMap2.java
@@ -0,0 +1,93 @@
+package bjc.esodata;
+
+import java.util.*;
+
+/**
+ * A revised version of {@link AbbrevMap}
+ *
+ * @author Ben Culkin
+ */
+public class AbbrevMap2 {
+ // Stores a mapping from strings, to strings that they could be abbreviations for
+ private Multimap<String, String> backing;
+
+ /**
+ * Create a new abbreviation map.
+ */
+ public AbbrevMap2() {
+ backing = new Multimap<>();
+ }
+
+ /**
+ * Add words to the map.
+ *
+ * @param words
+ * The words to add to the map.
+ */
+ public void add(String... words) {
+ for (String word : words) {
+ for (String substr : genAbbrevs(word)) {
+ backing.add(substr, word);
+ }
+ }
+ }
+
+ // Generate all of the strings a given word could be abbreviated as
+ private List<String> genAbbrevs(String word) {
+ List<String> retList = new ArrayList<>();
+
+ int len = word.length();
+
+ for (int i = 1; i <= len; i++) {
+ String substr = word.substring(0, i);
+
+ retList.add(substr);
+ }
+
+ return retList;
+ }
+
+ /**
+ * Remove words from the map.
+ *
+ * @param words
+ * The words to remove from the map.
+ */
+ public void removeWords(String... words) {
+ for (String word : words) {
+ for (String substr : genAbbrevs(word)) {
+ backing.remove(substr, word);
+ }
+ }
+ }
+
+ /**
+ * Get all of the strings that a string could be an abbreviation for.
+ *
+ * @param word
+ * The word to attempt to deabbreviate.
+ *
+ * @return All of the possible deabbreviations for that word.
+ */
+ public Set<String> deabbrevAll(String word) {
+ return backing.get(word);
+ }
+
+ /**
+ * Get the unambiguous thing the string is an abbreviation for.
+ *
+ * @param word
+ * The word to attempt to deabbreviate.
+ *
+ * @return The unambiguous deabbreviation of the string, or null if there isn't one.
+ */
+ public String deabbrev(String word) {
+ Set<String> st = backing.get(word);
+
+ if (st.size() == 1) {
+ return st.iterator().next();
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/bjc/esodata/Multimap.java b/src/main/java/bjc/esodata/Multimap.java
new file mode 100644
index 0000000..bb41b03
--- /dev/null
+++ b/src/main/java/bjc/esodata/Multimap.java
@@ -0,0 +1,110 @@
+package bjc.esodata;
+
+import java.util.*;
+
+import bjc.data.*;
+
+/**
+ * A map that has support for multiple values for a given key.
+ *
+ * Whenever you give another value for a key, that is then returned for that key. About the only
+ * somewhat complex thing, is that, if you add the same key-value pair multiple times, it will only
+ * show up once. However, you will have to remove that pair as many times as you added it.
+ *
+ * @author Ben Culkin
+ */
+public class Multimap<KeyType, ValueType> {
+ private Map<KeyType, ThresholdSet<ValueType>> backing;
+
+ /**
+ * Create a new empty multimap.
+ */
+ public Multimap() {
+ backing = new HashMap<>();
+ }
+
+ /**
+ * Add a key-value mapping to the map.
+ *
+ * @param key
+ * The key to store the value under.
+ *
+ * @param value
+ * The value to store.
+ */
+ public void add(KeyType key, ValueType value) {
+ ThresholdSet<ValueType> container = backing.computeIfAbsent(key,
+ (k) -> new ThresholdSet());
+
+ container.add(value);
+ }
+
+ /**
+ * Delete a particular key-value mapping from the map.
+ *
+ * @param key
+ * The key of the mapping to remove.
+ *
+ * @param value
+ * The value of the mapping to remove.
+ */
+ public void remove(KeyType key, ValueType value) {
+ // We have no values for that key; bail.
+ if (!backing.containsKey(key)) return;
+
+ backing.get(key).remove(value);
+ }
+
+ /**
+ * Delete all of the values associated with a particular key.
+ *
+ * @param key
+ * The key to remove values for.
+ */
+ public void remove(KeyType key) {
+ backing.remove(key);
+ }
+
+ /**
+ * Get a set containing all of the values that are recorded for that key.
+ *
+ * @param key
+ * The key to look up values for.
+ *
+ * @return A set containing all of the values that have been mapped to that key.
+ */
+ public Set<ValueType> get(KeyType key) {
+ if (!backing.containsKey(key)) return new HashSet<>();
+
+ return backing.get(key).values();
+ }
+
+ /**
+ * Check if there is at least one value mapped to the given key.
+ *
+ * @param key
+ * The key to check for mappings for.
+ *
+ * @return Whether or not there is at least one value mapped to the key.
+ */
+ public boolean contains(KeyType key) {
+ return backing.containsKey(key);
+ }
+
+ /**
+ * Check if there is at least one instance of a particular key-value mapping.
+ *
+ * @param key
+ * The key to check for mappings for.
+ *
+ * @param value
+ * The value to check for mappings for.
+ *
+ * @return Whether or not there is at least one instance of the given key-value mapping.
+ */
+ public boolean contains(KeyType key, ValueType value) {
+ if (!backing.containsKey(key)) return false;
+
+ return backing.get(key).contains(value) > 0;
+ }
+}
diff --git a/src/main/java/bjc/esodata/ThresholdSet.java b/src/main/java/bjc/esodata/ThresholdSet.java
index 245eb5f..cc7c0e1 100644
--- a/src/main/java/bjc/esodata/ThresholdSet.java
+++ b/src/main/java/bjc/esodata/ThresholdSet.java
@@ -2,6 +2,8 @@ package bjc.esodata;
import java.util.*;
+import bjc.data.*;
+
/**
* Represents a counted set, that overflows to a map.
*
@@ -80,7 +82,8 @@ public class ThresholdSet<KeyType> {
private Set<KeyType> keySet;
// @TODO :CountMap Ben Culkin 6/19/2019
- // Replace this with a CountSet or some equivalent concept, whenever that gets written
+ // Replace this with a CountSet or some equivalent concept, whenever that gets written, if that
+ // gets written
private Map<KeyType, Integer> keyMap;
/**
@@ -94,8 +97,9 @@ public class ThresholdSet<KeyType> {
/**
* Add multiple keys at once to the map.
*
- * @param keys
- * The keys to add.
+ * @param key
+ * The keys to add.
+ *
* @return An array containing the results of adding the keys.
*/
public int[] addKeys(KeyType... keys) {
@@ -112,7 +116,8 @@ public class ThresholdSet<KeyType> {
* Add a key to the collection.
*
* @param key
- * The key to add to the collection.
+ * The key to add to the collection.
+ *
* @return The number of times that key now exists in the collection. Should always be &lt; 0.
*/
public int add(KeyType key) {
@@ -227,6 +232,20 @@ public class ThresholdSet<KeyType> {
}
/**
+ * Get a set containing all of the values that are in this set at least once.
+ *
+ * @return A set containing every value that occurs at least once in this set.
+ */
+ public Set<KeyType> values() {
+ Set<KeyType> retSet = new HashSet<>();
+
+ retSet.addAll(keySet);
+ retSet.addAll(keyMap.keySet());
+
+ return retSet;
+ }
+
+ /**
* Get a view of this collection as a java.util.Set.
*
* @return A view of the collection as a set.