diff options
| author | bculkin2442 <bjculkin@mix.wvu.edu> | 2019-07-27 23:10:16 -0400 |
|---|---|---|
| committer | bculkin2442 <bjculkin@mix.wvu.edu> | 2019-07-27 23:10:16 -0400 |
| commit | fadc9d01f662ab001d9fdd0fd92c5f0c177557cd (patch) | |
| tree | 0747e6746c3b7f33016bf8ed0324bd6972b09795 /src | |
| parent | a623c8fafaa103a902fbdb4936b2ee78463ae5ba (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')
| -rw-r--r-- | src/main/java/bjc/esodata/AbbrevMap.java | 206 | ||||
| -rw-r--r-- | src/main/java/bjc/esodata/AbbrevMap2.java | 93 | ||||
| -rw-r--r-- | src/main/java/bjc/esodata/Multimap.java | 110 | ||||
| -rw-r--r-- | src/main/java/bjc/esodata/ThresholdSet.java | 27 |
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 < 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. |
