38 private final TreeMap<String, V> m_allPrefixes;
39 private final Set<Map.Entry<String, V>> m_entrySet;
40 private final Set<String> m_keySet;
41 private final Collection<V> m_values;
44 @SuppressWarnings(
"this-escape")
46 m_prefixTrie =
new StringPrefixTrie<>();
47 m_allPrefixes =
new TreeMap<>();
48 m_entrySet =
new EntrySet();
49 m_keySet =
new KeySet();
50 m_values =
new Values();
55 return m_prefixTrie.containsPrefix(prefix);
58 private String storedKey(String key) {
63 public V
put(String prefix, V value) {
64 Objects.requireNonNull(prefix,
"The prefix may not be null");
65 Objects.requireNonNull(value,
"The value may not be null");
67 V previousValue = m_prefixTrie.add(prefix, value);
68 m_allPrefixes.put(storedKey(prefix), value);
74 return m_allPrefixes.size();
80 m_allPrefixes.clear();
84 public V
remove(String prefix) {
85 Objects.requireNonNull(prefix,
"The prefix may not be null");
86 V oldValue = m_prefixTrie.remove(prefix);
87 if (oldValue !=
null) {
88 m_allPrefixes.remove(storedKey(prefix));
94 public V
get(String prefix) {
95 return m_prefixTrie.get(prefix);
100 return m_prefixTrie.getShortestMatch(input);
105 return m_prefixTrie.getLongestMatch(input);
110 return m_prefixTrie.getAllMatches(input);
114 public Set<Map.Entry<String, V>> entrySet() {
119 public boolean containsKey(Object key) {
120 return key instanceof String && m_allPrefixes.containsKey(storedKey((String) key));
124 public boolean containsValue(Object value) {
125 return m_allPrefixes.containsValue(value);
129 public Set<String> keySet() {
134 public Collection<V> values() {
139 public boolean equals(Object obj) {
140 return obj ==
this || m_allPrefixes.equals(obj);
144 public int hashCode() {
145 return m_allPrefixes.hashCode();
148 private abstract class BackingIterator<T>
implements Iterator<T> {
149 private final Iterator<Map.Entry<String, V>> m_iterator = m_allPrefixes.entrySet().iterator();
150 private Map.Entry<String, V> m_current;
153 public boolean hasNext() {
154 return m_iterator.hasNext();
157 protected Map.Entry<String, V> nextEntry() {
158 m_current = m_iterator.next();
163 public void remove() {
164 if (m_current ==
null) {
165 throw new IllegalStateException();
167 String key = m_current.getKey();
169 m_prefixTrie.remove(key);
174 private final class EntryIterator
extends BackingIterator<Map.Entry<String, V>> {
176 public Map.Entry<String, V> next() {
177 return new PrefixEntry(nextEntry());
181 private final class KeyIterator
extends BackingIterator<String> {
183 public String next() {
184 return nextEntry().getKey();
188 private final class ValueIterator
extends BackingIterator<V> {
191 return nextEntry().getValue();
195 private final class PrefixEntry
implements Map.Entry<String, V> {
196 private final Map.Entry<String, V> m_entry;
198 PrefixEntry(Map.Entry<String, V> entry) {
203 public String getKey() {
204 return m_entry.getKey();
208 public V getValue() {
209 return m_entry.getValue();
213 public V setValue(V value) {
214 Objects.requireNonNull(value,
"The value may not be null");
215 m_prefixTrie.add(getKey(), value);
216 return m_entry.setValue(value);
220 public boolean equals(Object obj) {
221 if (!(obj instanceof Map.Entry<?, ?>)) {
224 Map.Entry<?, ?> other = (Map.Entry<?, ?>) obj;
225 return Objects.equals(getKey(), other.getKey())
226 && Objects.equals(getValue(), other.getValue());
230 public int hashCode() {
231 return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
235 private final class EntrySet
extends AbstractSet<Map.Entry<String, V>> {
237 public Iterator<Map.Entry<String, V>> iterator() {
238 return new EntryIterator();
247 public boolean contains(Object obj) {
248 if (!(obj instanceof Map.Entry<?, ?>)) {
251 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
252 Object key = entry.getKey();
253 if (!(key instanceof String)) {
256 String prefix = storedKey((String) key);
257 return m_allPrefixes.containsKey(prefix)
258 && Objects.equals(m_allPrefixes.get(prefix), entry.getValue());
262 public boolean remove(Object obj) {
263 if (!(obj instanceof Map.Entry<?, ?>)) {
266 Map.Entry<?, ?> entry = (Map.Entry<?, ?>) obj;
267 Object key = entry.getKey();
268 if (!(key instanceof String)) {
271 String prefix = storedKey((String) key);
272 if (!m_allPrefixes.containsKey(prefix)
273 || !Objects.equals(m_allPrefixes.get(prefix), entry.getValue())) {
281 public void clear() {
286 private final class KeySet
extends AbstractSet<String> {
288 public Iterator<String> iterator() {
289 return new KeyIterator();
298 public boolean contains(Object key) {
303 public boolean remove(Object key) {
304 return key instanceof String &&
StringPrefixMap.this.remove((String) key) !=
null;
308 public void clear() {
313 private final class Values
extends AbstractCollection<V> {
315 public Iterator<V> iterator() {
316 return new ValueIterator();
325 public boolean contains(Object value) {
330 public void clear() {