package com.miguelfonseca.completely.text.index; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import static com.miguelfonseca.completely.common.Precondition.checkPointer; /** * Hashing based implementation of the {@link Index} interface. * * <p>Note that this implementation is not synchronized. */ public class HashMultiMap<V> extends AbstractIndex<V> implements Index<V> { private final Map<String, Set<V>> map; /** * Constructs a new {@link HashMultiMap}. */ public HashMultiMap() { map = new HashMap<>(); } @Override public void clear() { map.clear(); } @Override public Set<V> getAll(String key) { checkPointer(key != null); Set<V> value = map.get(key); if (value != null) { return new HashSet<>(value); } return new HashSet<>(); } @Override public boolean isEmpty() { return map.isEmpty(); } @Override public boolean putAll(String key, Collection<V> values) { checkPointer(key != null); checkPointer(values != null); Set<V> value = map.get(key); if (value == null) { value = new HashSet<>(); map.put(key, value); } return value.addAll(values); } @Override public boolean removeAll(Collection<V> values) { checkPointer(values != null); boolean result = false; for (Iterator<Set<V>> iterator = map.values().iterator(); iterator.hasNext();) { Set<V> value = iterator.next(); if (value.removeAll(values)) { result = true; } if (value.isEmpty()) { iterator.remove(); } } return result; } @Override public Set<V> removeAll(String key) { checkPointer(key != null); Set<V> value = map.remove(key); return value != null ? value : new HashSet<>(); } @Override public boolean removeAll(String key, Collection<V> values) { checkPointer(key != null); checkPointer(values != null); Set<V> value = map.get(key); if (value != null) { boolean result = value.removeAll(values); if (value.isEmpty()) { map.remove(key); } return result; } return false; } @Override public int size() { int size = 0; for (Entry<String, Set<V>> entry : map.entrySet()) { size += entry.getValue().size(); } return size; } }