diff --git a/datastructures-multi/build.gradle b/datastructures-multi/build.gradle
deleted file mode 100644
index 4c5fd3a..0000000
--- a/datastructures-multi/build.gradle
+++ /dev/null
@@ -1,3 +0,0 @@
-dependencies {
- api project(':datastructures-immutable')
-}
diff --git a/datastructures-multi/src/main/java/module-info.java b/datastructures-multi/src/main/java/module-info.java
deleted file mode 100644
index f871cdd..0000000
--- a/datastructures-multi/src/main/java/module-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-module org.xbib.datastructures.multi {
- exports org.xbib.datastructures.multi;
- requires org.xbib.datastructures.api;
- requires org.xbib.datastructures.immutable;
-}
diff --git a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultimap.java b/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultimap.java
deleted file mode 100644
index 809daa4..0000000
--- a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultimap.java
+++ /dev/null
@@ -1,1689 +0,0 @@
-package org.xbib.datastructures.multi;
-
-import static java.util.Objects.requireNonNull;
-
-import java.util.AbstractCollection;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NavigableMap;
-import java.util.NavigableSet;
-import java.util.Objects;
-import java.util.RandomAccess;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.Spliterator;
-import java.util.function.BiConsumer;
-import org.xbib.datastructures.api.Multimap;
-import org.xbib.datastructures.api.Multiset;
-import org.xbib.datastructures.api.SetMultimap;
-
-/**
- * Basic implementation of the {@link Multimap} interface. This class represents a multimap as a map
- * that associates each key with a collection of values. All methods of {@link Multimap} are
- * supported, including those specified as optional in the interface.
- *
- *
To implement a multimap, a subclass must define the method {@link #createCollection()}, which
- * creates an empty collection of values for a key.
- *
- *
The multimap constructor takes a map that has a single entry for each distinct key. When you
- * insert a key-value pair with a key that isn't already in the multimap, {@code
- * AbstractMapBasedMultimap} calls {@link #createCollection()} to create the collection of values
- * for that key. The subclass should not call {@link #createCollection()} directly, and a new
- * instance should be created every time the method is called.
- *
- *
For example, the subclass could pass a {@link java.util.TreeMap} during construction, and
- * {@link #createCollection()} could return a {@link java.util.TreeSet}, in which case the
- * multimap's iterators would propagate through the keys and values in sorted order.
- *
- *
Keys and values may be null, as long as the underlying collection classes support null
- * elements.
- *
- *
The collections created by {@link #createCollection()} may or may not allow duplicates. If the
- * collection, such as a {@link Set}, does not support duplicates, an added key-value pair will
- * replace an existing pair with the same key and value, if such a pair is present. With collections
- * like {@link List} that allow duplicates, the collection will keep the existing key-value pairs
- * while adding a new pair.
- *
- *
This class is not threadsafe when any concurrent operations update the multimap, even if the
- * underlying map and {@link #createCollection()} method return threadsafe classes. Concurrent read
- * operations will work correctly. To allow concurrent update operations, wrap your multimap with a
- * call to {@link Multimaps#synchronizedMultimap}.
- *
- *
For serialization to work, the subclass must specify explicit {@code readObject} and {@code
- * writeObject} methods.
- */
-abstract class AbstractMapBasedMultimap
- extends AbstractMultimap {
- /*
- * Here's an outline of the overall design.
- *
- * The map variable contains the collection of values associated with each
- * key. When a key-value pair is added to a multimap that didn't previously
- * contain any values for that key, a new collection generated by
- * createCollection is added to the map. That same collection instance
- * remains in the map as long as the multimap has any values for the key. If
- * all values for the key are removed, the key and collection are removed
- * from the map.
- *
- * The get method returns a WrappedCollection, which decorates the collection
- * in the map (if the key is present) or an empty collection (if the key is
- * not present). When the collection delegate in the WrappedCollection is
- * empty, the multimap may contain subsequently added values for that key. To
- * handle that situation, the WrappedCollection checks whether map contains
- * an entry for the provided key, and if so replaces the delegate.
- */
-
- private transient Map> map;
- private transient int totalSize;
-
- /**
- * Creates a new multimap that uses the provided map.
- *
- * @param map place to store the mapping from each key to its corresponding values
- * @throws IllegalArgumentException if {@code map} is not empty
- */
- protected AbstractMapBasedMultimap(Map> map) {
- checkArgument(map.isEmpty());
- this.map = map;
- }
-
- /** Used during deserialization only. */
- final void setMap(Map> map) {
- this.map = map;
- totalSize = 0;
- for (Collection values : map.values()) {
- checkArgument(!values.isEmpty());
- totalSize += values.size();
- }
- }
-
- /**
- * Creates an unmodifiable, empty collection of values.
- *
- * This is used in {@link #removeAll} on an empty key.
- */
- Collection createUnmodifiableEmptyCollection() {
- return unmodifiableCollectionSubclass(createCollection());
- }
-
- /**
- * Creates the collection of values for a single key.
- *
- * Collections with weak, soft, or phantom references are not supported. Each call to {@code
- * createCollection} should create a new instance.
- *
- *
The returned collection class determines whether duplicate key-value pairs are allowed.
- *
- * @return an empty collection of values
- */
- abstract Collection createCollection();
-
- /**
- * Creates the collection of values for an explicitly provided key. By default, it simply calls
- * {@link #createCollection()}, which is the correct behavior for most implementations. The {@link
- * LinkedHashMultimap} class overrides it.
- *
- * @param key key to associate with values in the collection
- * @return an empty collection of values
- */
- Collection createCollection(K key) {
- return createCollection();
- }
-
- Map> backingMap() {
- return map;
- }
-
- // Query Operations
-
- @Override
- public int size() {
- return totalSize;
- }
-
- @Override
- public boolean containsKey(Object key) {
- return map.containsKey(key);
- }
-
- // Modification Operations
-
- @Override
- public boolean put(K key, V value) {
- Collection collection = map.get(key);
- if (collection == null) {
- collection = createCollection(key);
- if (collection.add(value)) {
- totalSize++;
- map.put(key, collection);
- return true;
- } else {
- throw new AssertionError("New Collection violated the Collection spec");
- }
- } else if (collection.add(value)) {
- totalSize++;
- return true;
- } else {
- return false;
- }
- }
-
- private Collection getOrCreateCollection(K key) {
- Collection collection = map.get(key);
- if (collection == null) {
- collection = createCollection(key);
- map.put(key, collection);
- }
- return collection;
- }
-
- // Bulk Operations
-
- /**
- * {@inheritDoc}
- *
- * The returned collection is immutable.
- */
- @Override
- public Collection replaceValues(K key, Iterable extends V> values) {
- Iterator extends V> iterator = values.iterator();
- if (!iterator.hasNext()) {
- return removeAll(key);
- }
-
- // TODO(lowasser): investigate atomic failure?
- Collection collection = getOrCreateCollection(key);
- Collection oldValues = createCollection();
- oldValues.addAll(collection);
-
- totalSize -= collection.size();
- collection.clear();
-
- while (iterator.hasNext()) {
- if (collection.add(iterator.next())) {
- totalSize++;
- }
- }
-
- return unmodifiableCollectionSubclass(oldValues);
- }
-
- /**
- * {@inheritDoc}
- *
- * The returned collection is immutable.
- */
- @Override
- public Collection removeAll(Object key) {
- Collection collection = map.remove(key);
-
- if (collection == null) {
- return createUnmodifiableEmptyCollection();
- }
-
- Collection output = createCollection();
- output.addAll(collection);
- totalSize -= collection.size();
- collection.clear();
-
- return unmodifiableCollectionSubclass(output);
- }
-
- Collection unmodifiableCollectionSubclass(
- Collection collection) {
- return Collections.unmodifiableCollection(collection);
- }
-
- @Override
- public void clear() {
- // Clear each collection, to make previously returned collections empty.
- for (Collection collection : map.values()) {
- collection.clear();
- }
- map.clear();
- totalSize = 0;
- }
-
- // Views
-
- /**
- * {@inheritDoc}
- *
- * The returned collection is not serializable.
- */
- @Override
- public Collection get(K key) {
- Collection collection = map.get(key);
- if (collection == null) {
- collection = createCollection(key);
- }
- return wrapCollection(key, collection);
- }
-
- /**
- * Generates a decorated collection that remains consistent with the values in the multimap for
- * the provided key. Changes to the multimap may alter the returned collection, and vice versa.
- */
- Collection wrapCollection(K key, Collection collection) {
- return new WrappedCollection(key, collection, null);
- }
-
- final List wrapList(
- K key, List list, WrappedCollection ancestor) {
- return (list instanceof RandomAccess)
- ? new RandomAccessWrappedList(key, list, ancestor)
- : new WrappedList(key, list, ancestor);
- }
-
- /**
- * Collection decorator that stays in sync with the multimap values for a key. There are two kinds
- * of wrapped collections: full and subcollections. Both have a delegate pointing to the
- * underlying collection class.
- *
- * Full collections, identified by a null ancestor field, contain all multimap values for a
- * given key. Its delegate is a value in {@link AbstractMapBasedMultimap#map} whenever the
- * delegate is non-empty. The {@code refreshIfEmpty}, {@code removeIfEmpty}, and {@code addToMap}
- * methods ensure that the {@code WrappedCollection} and map remain consistent.
- *
- *
A subcollection, such as a sublist, contains some of the values for a given key. Its
- * ancestor field points to the full wrapped collection with all values for the key. The
- * subcollection {@code refreshIfEmpty}, {@code removeIfEmpty}, and {@code addToMap} methods call
- * the corresponding methods of the full wrapped collection.
- */
-
- class WrappedCollection extends AbstractCollection {
- final K key;
- Collection delegate;
- final WrappedCollection ancestor;
- final Collection ancestorDelegate;
-
- WrappedCollection(
- K key,
- Collection delegate,
- WrappedCollection ancestor) {
- this.key = key;
- this.delegate = delegate;
- this.ancestor = ancestor;
- this.ancestorDelegate = (ancestor == null) ? null : ancestor.getDelegate();
- }
-
- /**
- * If the delegate collection is empty, but the multimap has values for the key, replace the
- * delegate with the new collection for the key.
- *
- * For a subcollection, refresh its ancestor and validate that the ancestor delegate hasn't
- * changed.
- */
- void refreshIfEmpty() {
- if (ancestor != null) {
- ancestor.refreshIfEmpty();
- if (ancestor.getDelegate() != ancestorDelegate) {
- throw new ConcurrentModificationException();
- }
- } else if (delegate.isEmpty()) {
- Collection newDelegate = map.get(key);
- if (newDelegate != null) {
- delegate = newDelegate;
- }
- }
- }
-
- /**
- * If collection is empty, remove it from {@code AbstractMapBasedMultimap.this.map}. For
- * subcollections, check whether the ancestor collection is empty.
- */
- void removeIfEmpty() {
- if (ancestor != null) {
- ancestor.removeIfEmpty();
- } else if (delegate.isEmpty()) {
- map.remove(key);
- }
- }
-
-
- K getKey() {
- return key;
- }
-
- /**
- * Add the delegate to the map. Other {@code WrappedCollection} methods should call this method
- * after adding elements to a previously empty collection.
- *
- * Subcollection add the ancestor's delegate instead.
- */
- void addToMap() {
- if (ancestor != null) {
- ancestor.addToMap();
- } else {
- map.put(key, delegate);
- }
- }
-
- @Override
- public int size() {
- refreshIfEmpty();
- return delegate.size();
- }
-
- @Override
- public boolean equals(Object object) {
- if (object == this) {
- return true;
- }
- refreshIfEmpty();
- return delegate.equals(object);
- }
-
- @Override
- public int hashCode() {
- refreshIfEmpty();
- return delegate.hashCode();
- }
-
- @Override
- public String toString() {
- refreshIfEmpty();
- return delegate.toString();
- }
-
- Collection getDelegate() {
- return delegate;
- }
-
- @Override
- public Iterator iterator() {
- refreshIfEmpty();
- return new WrappedIterator();
- }
-
- @Override
- public Spliterator spliterator() {
- refreshIfEmpty();
- return delegate.spliterator();
- }
-
- /** Collection iterator for {@code WrappedCollection}. */
- class WrappedIterator implements Iterator {
- final Iterator delegateIterator;
- final Collection originalDelegate = delegate;
-
- WrappedIterator() {
- delegateIterator = iteratorOrListIterator(delegate);
- }
-
- WrappedIterator(Iterator delegateIterator) {
- this.delegateIterator = delegateIterator;
- }
-
- /**
- * If the delegate changed since the iterator was created, the iterator is no longer valid.
- */
- void validateIterator() {
- refreshIfEmpty();
- if (delegate != originalDelegate) {
- throw new ConcurrentModificationException();
- }
- }
-
- @Override
- public boolean hasNext() {
- validateIterator();
- return delegateIterator.hasNext();
- }
-
- @Override
-
- public V next() {
- validateIterator();
- return delegateIterator.next();
- }
-
- @Override
- public void remove() {
- delegateIterator.remove();
- totalSize--;
- removeIfEmpty();
- }
-
- Iterator getDelegateIterator() {
- validateIterator();
- return delegateIterator;
- }
- }
-
- @Override
- public boolean add(V value) {
- refreshIfEmpty();
- boolean wasEmpty = delegate.isEmpty();
- boolean changed = delegate.add(value);
- if (changed) {
- totalSize++;
- if (wasEmpty) {
- addToMap();
- }
- }
- return changed;
- }
-
-
- WrappedCollection getAncestor() {
- return ancestor;
- }
-
- // The following methods are provided for better performance.
-
- @Override
- public boolean addAll(Collection extends V> collection) {
- if (collection.isEmpty()) {
- return false;
- }
- int oldSize = size(); // calls refreshIfEmpty
- boolean changed = delegate.addAll(collection);
- if (changed) {
- int newSize = delegate.size();
- totalSize += (newSize - oldSize);
- if (oldSize == 0) {
- addToMap();
- }
- }
- return changed;
- }
-
- @Override
- public boolean contains(Object o) {
- refreshIfEmpty();
- return delegate.contains(o);
- }
-
- @Override
- public boolean containsAll(Collection> c) {
- refreshIfEmpty();
- return delegate.containsAll(c);
- }
-
- @Override
- public void clear() {
- int oldSize = size(); // calls refreshIfEmpty
- if (oldSize == 0) {
- return;
- }
- delegate.clear();
- totalSize -= oldSize;
- removeIfEmpty(); // maybe shouldn't be removed if this is a sublist
- }
-
- @Override
- public boolean remove(Object o) {
- refreshIfEmpty();
- boolean changed = delegate.remove(o);
- if (changed) {
- totalSize--;
- removeIfEmpty();
- }
- return changed;
- }
-
- @Override
- public boolean removeAll(Collection> c) {
- if (c.isEmpty()) {
- return false;
- }
- int oldSize = size(); // calls refreshIfEmpty
- boolean changed = delegate.removeAll(c);
- if (changed) {
- int newSize = delegate.size();
- totalSize += (newSize - oldSize);
- removeIfEmpty();
- }
- return changed;
- }
-
- @Override
- public boolean retainAll(Collection> c) {
- Objects.requireNonNull(c);
- int oldSize = size(); // calls refreshIfEmpty
- boolean changed = delegate.retainAll(c);
- if (changed) {
- int newSize = delegate.size();
- totalSize += (newSize - oldSize);
- removeIfEmpty();
- }
- return changed;
- }
- }
-
- private static Iterator iteratorOrListIterator(
- Collection collection) {
- return (collection instanceof List)
- ? ((List) collection).listIterator()
- : collection.iterator();
- }
-
- /** Set decorator that stays in sync with the multimap values for a key. */
-
- class WrappedSet extends WrappedCollection implements Set {
- WrappedSet(K key, Set delegate) {
- super(key, delegate, null);
- }
-
- @Override
- public boolean removeAll(Collection> c) {
- if (c.isEmpty()) {
- return false;
- }
- int oldSize = size(); // calls refreshIfEmpty
-
- // Guava issue 1013: AbstractSet and most JDK set implementations are
- // susceptible to quadratic removeAll performance on lists;
- // use a slightly smarter implementation here
- boolean changed = Sets.removeAllImpl((Set) delegate, c);
- if (changed) {
- int newSize = delegate.size();
- totalSize += (newSize - oldSize);
- removeIfEmpty();
- }
- return changed;
- }
- }
-
- /** SortedSet decorator that stays in sync with the multimap values for a key. */
-
- class WrappedSortedSet extends WrappedCollection implements SortedSet {
- WrappedSortedSet(
- K key,
- SortedSet delegate,
- WrappedCollection ancestor) {
- super(key, delegate, ancestor);
- }
-
- SortedSet getSortedSetDelegate() {
- return (SortedSet) getDelegate();
- }
-
- @Override
-
- public Comparator super V> comparator() {
- return getSortedSetDelegate().comparator();
- }
-
- @Override
-
- public V first() {
- refreshIfEmpty();
- return getSortedSetDelegate().first();
- }
-
- @Override
-
- public V last() {
- refreshIfEmpty();
- return getSortedSetDelegate().last();
- }
-
- @Override
- public SortedSet headSet(V toElement) {
- refreshIfEmpty();
- return new WrappedSortedSet(
- getKey(),
- getSortedSetDelegate().headSet(toElement),
- (getAncestor() == null) ? this : getAncestor());
- }
-
- @Override
- public SortedSet subSet(V fromElement, V toElement) {
- refreshIfEmpty();
- return new WrappedSortedSet(
- getKey(),
- getSortedSetDelegate().subSet(fromElement, toElement),
- (getAncestor() == null) ? this : getAncestor());
- }
-
- @Override
- public SortedSet tailSet(V fromElement) {
- refreshIfEmpty();
- return new WrappedSortedSet(
- getKey(),
- getSortedSetDelegate().tailSet(fromElement),
- (getAncestor() == null) ? this : getAncestor());
- }
- }
-
-
- class WrappedNavigableSet extends WrappedSortedSet implements NavigableSet {
- WrappedNavigableSet(
- K key,
- NavigableSet delegate,
- WrappedCollection ancestor) {
- super(key, delegate, ancestor);
- }
-
- @Override
- NavigableSet getSortedSetDelegate() {
- return (NavigableSet) super.getSortedSetDelegate();
- }
-
- @Override
-
- public V lower(V v) {
- return getSortedSetDelegate().lower(v);
- }
-
- @Override
-
- public V floor(V v) {
- return getSortedSetDelegate().floor(v);
- }
-
- @Override
-
- public V ceiling(V v) {
- return getSortedSetDelegate().ceiling(v);
- }
-
- @Override
-
- public V higher(V v) {
- return getSortedSetDelegate().higher(v);
- }
-
- @Override
-
- public V pollFirst() {
- return Iterators.pollNext(iterator());
- }
-
- @Override
-
- public V pollLast() {
- return Iterators.pollNext(descendingIterator());
- }
-
- private NavigableSet wrap(NavigableSet wrapped) {
- return new WrappedNavigableSet(key, wrapped, (getAncestor() == null) ? this : getAncestor());
- }
-
- @Override
- public NavigableSet descendingSet() {
- return wrap(getSortedSetDelegate().descendingSet());
- }
-
- @Override
- public Iterator descendingIterator() {
- return new WrappedIterator(getSortedSetDelegate().descendingIterator());
- }
-
- @Override
- public NavigableSet subSet(
- V fromElement,
- boolean fromInclusive,
- V toElement,
- boolean toInclusive) {
- return wrap(
- getSortedSetDelegate().subSet(fromElement, fromInclusive, toElement, toInclusive));
- }
-
- @Override
- public NavigableSet headSet(V toElement, boolean inclusive) {
- return wrap(getSortedSetDelegate().headSet(toElement, inclusive));
- }
-
- @Override
- public NavigableSet tailSet(V fromElement, boolean inclusive) {
- return wrap(getSortedSetDelegate().tailSet(fromElement, inclusive));
- }
- }
-
- /** List decorator that stays in sync with the multimap values for a key. */
-
- class WrappedList extends WrappedCollection implements List {
- WrappedList(
- K key, List delegate, WrappedCollection ancestor) {
- super(key, delegate, ancestor);
- }
-
- List getListDelegate() {
- return (List) getDelegate();
- }
-
- @Override
- public boolean addAll(int index, Collection extends V> c) {
- if (c.isEmpty()) {
- return false;
- }
- int oldSize = size(); // calls refreshIfEmpty
- boolean changed = getListDelegate().addAll(index, c);
- if (changed) {
- int newSize = getDelegate().size();
- totalSize += (newSize - oldSize);
- if (oldSize == 0) {
- addToMap();
- }
- }
- return changed;
- }
-
- @Override
-
- public V get(int index) {
- refreshIfEmpty();
- return getListDelegate().get(index);
- }
-
- @Override
-
- public V set(int index, V element) {
- refreshIfEmpty();
- return getListDelegate().set(index, element);
- }
-
- @Override
- public void add(int index, V element) {
- refreshIfEmpty();
- boolean wasEmpty = getDelegate().isEmpty();
- getListDelegate().add(index, element);
- totalSize++;
- if (wasEmpty) {
- addToMap();
- }
- }
-
- @Override
-
- public V remove(int index) {
- refreshIfEmpty();
- V value = getListDelegate().remove(index);
- totalSize--;
- removeIfEmpty();
- return value;
- }
-
- @Override
- public int indexOf(Object o) {
- refreshIfEmpty();
- return getListDelegate().indexOf(o);
- }
-
- @Override
- public int lastIndexOf(Object o) {
- refreshIfEmpty();
- return getListDelegate().lastIndexOf(o);
- }
-
- @Override
- public ListIterator listIterator() {
- refreshIfEmpty();
- return new WrappedListIterator();
- }
-
- @Override
- public ListIterator listIterator(int index) {
- refreshIfEmpty();
- return new WrappedListIterator(index);
- }
-
- @Override
- public List subList(int fromIndex, int toIndex) {
- refreshIfEmpty();
- return wrapList(
- getKey(),
- getListDelegate().subList(fromIndex, toIndex),
- (getAncestor() == null) ? this : getAncestor());
- }
-
- /** ListIterator decorator. */
- private class WrappedListIterator extends WrappedIterator implements ListIterator {
- WrappedListIterator() {}
-
- public WrappedListIterator(int index) {
- super(getListDelegate().listIterator(index));
- }
-
- private ListIterator getDelegateListIterator() {
- return (ListIterator) getDelegateIterator();
- }
-
- @Override
- public boolean hasPrevious() {
- return getDelegateListIterator().hasPrevious();
- }
-
- @Override
-
- public V previous() {
- return getDelegateListIterator().previous();
- }
-
- @Override
- public int nextIndex() {
- return getDelegateListIterator().nextIndex();
- }
-
- @Override
- public int previousIndex() {
- return getDelegateListIterator().previousIndex();
- }
-
- @Override
- public void set(V value) {
- getDelegateListIterator().set(value);
- }
-
- @Override
- public void add(V value) {
- boolean wasEmpty = isEmpty();
- getDelegateListIterator().add(value);
- totalSize++;
- if (wasEmpty) {
- addToMap();
- }
- }
- }
- }
-
- /**
- * List decorator that stays in sync with the multimap values for a key and supports rapid random
- * access.
- */
- private class RandomAccessWrappedList extends WrappedList implements RandomAccess {
- RandomAccessWrappedList(
- K key, List delegate, WrappedCollection ancestor) {
- super(key, delegate, ancestor);
- }
- }
-
- @Override
- Set createKeySet() {
- return new KeySet(map);
- }
-
- final Set createMaybeNavigableKeySet() {
- if (map instanceof NavigableMap) {
- return new NavigableKeySet((NavigableMap>) map);
- } else if (map instanceof SortedMap) {
- return new SortedKeySet((SortedMap>) map);
- } else {
- return new KeySet(map);
- }
- }
-
-
- private class KeySet extends MapsKeySet> {
- KeySet(final Map> subMap) {
- super(subMap);
- }
-
- @Override
- public Iterator iterator() {
- final Iterator>> entryIterator = map().entrySet().iterator();
- return new Iterator() {
- Entry> entry;
-
- @Override
- public boolean hasNext() {
- return entryIterator.hasNext();
- }
-
- @Override
-
- public K next() {
- entry = entryIterator.next();
- return entry.getKey();
- }
-
- @Override
- public void remove() {
- checkState(entry != null, "no calls to next() since the last call to remove()");
- Collection collection = entry.getValue();
- entryIterator.remove();
- totalSize -= collection.size();
- collection.clear();
- entry = null;
- }
- };
- }
-
- // The following methods are included for better performance.
-
- @Override
- public Spliterator spliterator() {
- return map().keySet().spliterator();
- }
-
- @Override
- public boolean remove(Object key) {
- int count = 0;
- Collection collection = map().remove(key);
- if (collection != null) {
- count = collection.size();
- collection.clear();
- totalSize -= count;
- }
- return count > 0;
- }
-
- @Override
- public void clear() {
- Iterators.clear(iterator());
- }
-
- @Override
- public boolean containsAll(Collection> c) {
- return map().keySet().containsAll(c);
- }
-
- @Override
- public boolean equals(Object object) {
- return this == object || this.map().keySet().equals(object);
- }
-
- @Override
- public int hashCode() {
- return map().keySet().hashCode();
- }
- }
-
-
- private class SortedKeySet extends KeySet implements SortedSet {
-
- SortedKeySet(SortedMap> subMap) {
- super(subMap);
- }
-
- SortedMap> sortedMap() {
- return (SortedMap>) super.map();
- }
-
- @Override
-
- public Comparator super K> comparator() {
- return sortedMap().comparator();
- }
-
- @Override
-
- public K first() {
- return sortedMap().firstKey();
- }
-
- @Override
- public SortedSet headSet(K toElement) {
- return new SortedKeySet(sortedMap().headMap(toElement));
- }
-
- @Override
-
- public K last() {
- return sortedMap().lastKey();
- }
-
- @Override
- public SortedSet subSet(K fromElement, K toElement) {
- return new SortedKeySet(sortedMap().subMap(fromElement, toElement));
- }
-
- @Override
- public SortedSet tailSet(K fromElement) {
- return new SortedKeySet(sortedMap().tailMap(fromElement));
- }
- }
-
-
- class NavigableKeySet extends SortedKeySet implements NavigableSet {
- NavigableKeySet(NavigableMap> subMap) {
- super(subMap);
- }
-
- @Override
- NavigableMap> sortedMap() {
- return (NavigableMap>) super.sortedMap();
- }
-
- @Override
-
- public K lower(K k) {
- return sortedMap().lowerKey(k);
- }
-
- @Override
-
- public K floor(K k) {
- return sortedMap().floorKey(k);
- }
-
- @Override
-
- public K ceiling(K k) {
- return sortedMap().ceilingKey(k);
- }
-
- @Override
-
- public K higher(K k) {
- return sortedMap().higherKey(k);
- }
-
- @Override
-
- public K pollFirst() {
- return Iterators.pollNext(iterator());
- }
-
- @Override
-
- public K pollLast() {
- return Iterators.pollNext(descendingIterator());
- }
-
- @Override
- public NavigableSet descendingSet() {
- return new NavigableKeySet(sortedMap().descendingMap());
- }
-
- @Override
- public Iterator descendingIterator() {
- return descendingSet().iterator();
- }
-
- @Override
- public NavigableSet headSet(K toElement) {
- return headSet(toElement, false);
- }
-
- @Override
- public NavigableSet headSet(K toElement, boolean inclusive) {
- return new NavigableKeySet(sortedMap().headMap(toElement, inclusive));
- }
-
- @Override
- public NavigableSet subSet(
- K fromElement, K toElement) {
- return subSet(fromElement, true, toElement, false);
- }
-
- @Override
- public NavigableSet subSet(
- K fromElement,
- boolean fromInclusive,
- K toElement,
- boolean toInclusive) {
- return new NavigableKeySet(
- sortedMap().subMap(fromElement, fromInclusive, toElement, toInclusive));
- }
-
- @Override
- public NavigableSet tailSet(K fromElement) {
- return tailSet(fromElement, true);
- }
-
- @Override
- public NavigableSet tailSet(K fromElement, boolean inclusive) {
- return new NavigableKeySet(sortedMap().tailMap(fromElement, inclusive));
- }
- }
-
- /** Removes all values for the provided key. */
- private void removeValuesForKey(Object key) {
- Collection collection = Maps.safeRemove(map, key);
-
- if (collection != null) {
- int count = collection.size();
- collection.clear();
- totalSize -= count;
- }
- }
-
- private abstract class Itr implements Iterator {
- final Iterator>> keyIterator;
- K key;
- Collection collection;
- Iterator valueIterator;
-
- Itr() {
- keyIterator = map.entrySet().iterator();
- key = null;
- collection = null;
- valueIterator = Iterators.emptyModifiableIterator();
- }
-
- abstract T output(K key, V value);
-
- @Override
- public boolean hasNext() {
- return keyIterator.hasNext() || valueIterator.hasNext();
- }
-
- @Override
- public T next() {
- if (!valueIterator.hasNext()) {
- Entry> mapEntry = keyIterator.next();
- key = mapEntry.getKey();
- collection = mapEntry.getValue();
- valueIterator = collection.iterator();
- }
- /*
- * uncheckedCastNullableTToT is safe: The first call to this method always enters the !hasNext() case and
- * populates key, after which it's never cleared.
- */
- return output(uncheckedCastNullableTToT(key), valueIterator.next());
- }
-
- @Override
- public void remove() {
- valueIterator.remove();
- /*
- * requireNonNull is safe because we've already initialized `collection`. If we hadn't, then
- * valueIterator.remove() would have failed.
- */
- if (requireNonNull(collection).isEmpty()) {
- keyIterator.remove();
- }
- totalSize--;
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * The iterator generated by the returned collection traverses the values for one key, followed
- * by the values of a second key, and so on.
- */
- @Override
- public Collection values() {
- return super.values();
- }
-
- @Override
- Collection createValues() {
- return new Values();
- }
-
- @Override
- Iterator valueIterator() {
- return new Itr() {
- @Override
-
- V output(K key, V value) {
- return value;
- }
- };
- }
-
- @Override
- Spliterator valueSpliterator() {
- return CollectSpliterators.flatMap(
- map.values().spliterator(), Collection::spliterator, Spliterator.SIZED, size());
- }
-
- /*
- * TODO(kevinb): should we copy this javadoc to each concrete class, so that
- * classes like LinkedHashMultimap that need to say something different are
- * still able to {@inheritDoc} all the way from Multimap?
- */
-
- @Override
- Multiset createKeys() {
- return new Multimaps.Keys(this);
- }
-
- /**
- * {@inheritDoc}
- *
- * The iterator generated by the returned collection traverses the values for one key, followed
- * by the values of a second key, and so on.
- *
- *
Each entry is an immutable snapshot of a key-value mapping in the multimap, taken at the
- * time the entry is returned by a method call to the collection or its iterator.
- */
- @Override
- public Collection> entries() {
- return super.entries();
- }
-
- @Override
- Collection> createEntries() {
- if (this instanceof SetMultimap) {
- return new EntrySet();
- } else {
- return new Entries();
- }
- }
-
- /**
- * Returns an iterator across all key-value map entries, used by {@code entries().iterator()} and
- * {@code values().iterator()}. The default behavior, which traverses the values for one key, the
- * values for a second key, and so on, suffices for most {@code AbstractMapBasedMultimap}
- * implementations.
- *
- * @return an iterator across map entries
- */
- @Override
- Iterator> entryIterator() {
- return new Itr>() {
- @Override
- Entry output(K key, V value) {
- return Maps.immutableEntry(key, value);
- }
- };
- }
-
- @Override
- Spliterator> entrySpliterator() {
- return CollectSpliterators.flatMap(
- map.entrySet().spliterator(),
- keyToValueCollectionEntry -> {
- K key = keyToValueCollectionEntry.getKey();
- Collection valueCollection = keyToValueCollectionEntry.getValue();
- return CollectSpliterators.map(
- valueCollection.spliterator(), (V value) -> Maps.immutableEntry(key, value));
- },
- Spliterator.SIZED,
- size());
- }
-
- @Override
- public void forEach(BiConsumer super K, ? super V> action) {
- Objects.requireNonNull(action);
- map.forEach(
- (key, valueCollection) -> valueCollection.forEach(value -> action.accept(key, value)));
- }
-
- @Override
- Map> createAsMap() {
- return new AsMap(map);
- }
-
- final Map> createMaybeNavigableAsMap() {
- if (map instanceof NavigableMap) {
- return new NavigableAsMap((NavigableMap>) map);
- } else if (map instanceof SortedMap) {
- return new SortedAsMap((SortedMap>) map);
- } else {
- return new AsMap(map);
- }
- }
-
-
- private class AsMap extends ViewCachingAbstractMap> {
- /**
- * Usually the same as map, but smaller for the headMap(), tailMap(), or subMap() of a
- * SortedAsMap.
- */
- final transient Map> submap;
-
- AsMap(Map> submap) {
- this.submap = submap;
- }
-
- @Override
- protected Set>> createEntrySet() {
- return new AsMapEntries();
- }
-
- // The following methods are included for performance.
-
- @Override
- public boolean containsKey(Object key) {
- return Maps.safeContainsKey(submap, key);
- }
-
- @Override
-
- public Collection get(Object key) {
- Collection collection = Maps.safeGet(submap, key);
- if (collection == null) {
- return null;
- }
- @SuppressWarnings("unchecked")
- K k = (K) key;
- return wrapCollection(k, collection);
- }
-
- @Override
- public Set keySet() {
- return AbstractMapBasedMultimap.this.keySet();
- }
-
- @Override
- public int size() {
- return submap.size();
- }
-
- @Override
-
- public Collection remove(Object key) {
- Collection collection = submap.remove(key);
- if (collection == null) {
- return null;
- }
-
- Collection output = createCollection();
- output.addAll(collection);
- totalSize -= collection.size();
- collection.clear();
- return output;
- }
-
- @Override
- public boolean equals(Object object) {
- return this == object || submap.equals(object);
- }
-
- @Override
- public int hashCode() {
- return submap.hashCode();
- }
-
- @Override
- public String toString() {
- return submap.toString();
- }
-
- @Override
- public void clear() {
- if (submap == map) {
- AbstractMapBasedMultimap.this.clear();
- } else {
- Iterators.clear(new AsMapIterator());
- }
- }
-
- Entry> wrapEntry(Entry> entry) {
- K key = entry.getKey();
- return Maps.immutableEntry(key, wrapCollection(key, entry.getValue()));
- }
-
-
- class AsMapEntries extends Maps.EntrySet> {
- @Override
- Map> map() {
- return AsMap.this;
- }
-
- @Override
- public Iterator>> iterator() {
- return new AsMapIterator();
- }
-
- @Override
- public Spliterator>> spliterator() {
- return CollectSpliterators.map(submap.entrySet().spliterator(), AsMap.this::wrapEntry);
- }
-
- // The following methods are included for performance.
-
- @Override
- public boolean contains(Object o) {
- return Collections2.safeContains(submap.entrySet(), o);
- }
-
- @Override
- public boolean remove(Object o) {
- if (!contains(o)) {
- return false;
- }
- // requireNonNull is safe because of the contains check.
- Entry, ?> entry = requireNonNull((Entry, ?>) o);
- removeValuesForKey(entry.getKey());
- return true;
- }
- }
-
- /** Iterator across all keys and value collections. */
- class AsMapIterator implements Iterator>> {
- final Iterator>> delegateIterator = submap.entrySet().iterator();
- Collection collection;
-
- @Override
- public boolean hasNext() {
- return delegateIterator.hasNext();
- }
-
- @Override
- public Entry> next() {
- Entry> entry = delegateIterator.next();
- collection = entry.getValue();
- return wrapEntry(entry);
- }
-
- @Override
- public void remove() {
- checkState(collection != null, "no calls to next() since the last call to remove()");
- delegateIterator.remove();
- totalSize -= collection.size();
- collection.clear();
- collection = null;
- }
- }
- }
-
-
- private class SortedAsMap extends AsMap implements SortedMap> {
- SortedAsMap(SortedMap> submap) {
- super(submap);
- }
-
- SortedMap> sortedMap() {
- return (SortedMap>) submap;
- }
-
- @Override
-
- public Comparator super K> comparator() {
- return sortedMap().comparator();
- }
-
- @Override
-
- public K firstKey() {
- return sortedMap().firstKey();
- }
-
- @Override
-
- public K lastKey() {
- return sortedMap().lastKey();
- }
-
- @Override
- public SortedMap> headMap(K toKey) {
- return new SortedAsMap(sortedMap().headMap(toKey));
- }
-
- @Override
- public SortedMap> subMap(
- K fromKey, K toKey) {
- return new SortedAsMap(sortedMap().subMap(fromKey, toKey));
- }
-
- @Override
- public SortedMap> tailMap(K fromKey) {
- return new SortedAsMap(sortedMap().tailMap(fromKey));
- }
-
- SortedSet sortedKeySet;
-
- // returns a SortedSet, even though returning a Set would be sufficient to
- // satisfy the SortedMap.keySet() interface
- @Override
- public SortedSet keySet() {
- SortedSet result = sortedKeySet;
- return (result == null) ? sortedKeySet = createKeySet() : result;
- }
-
- @Override
- SortedSet createKeySet() {
- return new SortedKeySet(sortedMap());
- }
- }
-
- class NavigableAsMap extends SortedAsMap implements NavigableMap> {
-
- NavigableAsMap(NavigableMap> submap) {
- super(submap);
- }
-
- @Override
- NavigableMap> sortedMap() {
- return (NavigableMap>) super.sortedMap();
- }
-
- @Override
-
- public Entry> lowerEntry(K key) {
- Entry> entry = sortedMap().lowerEntry(key);
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public K lowerKey(K key) {
- return sortedMap().lowerKey(key);
- }
-
- @Override
-
- public Entry> floorEntry(K key) {
- Entry> entry = sortedMap().floorEntry(key);
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public K floorKey(K key) {
- return sortedMap().floorKey(key);
- }
-
- @Override
-
- public Entry> ceilingEntry(K key) {
- Entry> entry = sortedMap().ceilingEntry(key);
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public K ceilingKey(K key) {
- return sortedMap().ceilingKey(key);
- }
-
- @Override
-
- public Entry> higherEntry(K key) {
- Entry> entry = sortedMap().higherEntry(key);
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public K higherKey(K key) {
- return sortedMap().higherKey(key);
- }
-
- @Override
-
- public Entry> firstEntry() {
- Entry> entry = sortedMap().firstEntry();
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public Entry> lastEntry() {
- Entry> entry = sortedMap().lastEntry();
- return (entry == null) ? null : wrapEntry(entry);
- }
-
- @Override
-
- public Entry> pollFirstEntry() {
- return pollAsMapEntry(entrySet().iterator());
- }
-
- @Override
-
- public Entry> pollLastEntry() {
- return pollAsMapEntry(descendingMap().entrySet().iterator());
- }
-
-
- Entry> pollAsMapEntry(Iterator>> entryIterator) {
- if (!entryIterator.hasNext()) {
- return null;
- }
- Entry> entry = entryIterator.next();
- Collection output = createCollection();
- output.addAll(entry.getValue());
- entryIterator.remove();
- return Maps.immutableEntry(entry.getKey(), unmodifiableCollectionSubclass(output));
- }
-
- @Override
- public NavigableMap> descendingMap() {
- return new NavigableAsMap(sortedMap().descendingMap());
- }
-
- @Override
- public NavigableSet keySet() {
- return (NavigableSet) super.keySet();
- }
-
- @Override
- NavigableSet createKeySet() {
- return new NavigableKeySet(sortedMap());
- }
-
- @Override
- public NavigableSet navigableKeySet() {
- return keySet();
- }
-
- @Override
- public NavigableSet descendingKeySet() {
- return descendingMap().navigableKeySet();
- }
-
- @Override
- public NavigableMap> subMap(
- K fromKey, K toKey) {
- return subMap(fromKey, true, toKey, false);
- }
-
- @Override
- public NavigableMap> subMap(
- K fromKey,
- boolean fromInclusive,
- K toKey,
- boolean toInclusive) {
- return new NavigableAsMap(sortedMap().subMap(fromKey, fromInclusive, toKey, toInclusive));
- }
-
- @Override
- public NavigableMap> headMap(K toKey) {
- return headMap(toKey, false);
- }
-
- @Override
- public NavigableMap> headMap(K toKey, boolean inclusive) {
- return new NavigableAsMap(sortedMap().headMap(toKey, inclusive));
- }
-
- @Override
- public NavigableMap> tailMap(K fromKey) {
- return tailMap(fromKey, true);
- }
-
- @Override
- public NavigableMap> tailMap(
- K fromKey, boolean inclusive) {
- return new NavigableAsMap(sortedMap().tailMap(fromKey, inclusive));
- }
- }
-}
diff --git a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultiset.java b/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultiset.java
deleted file mode 100644
index 2fa62e4..0000000
--- a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMapBasedMultiset.java
+++ /dev/null
@@ -1,321 +0,0 @@
-package org.xbib.datastructures.multi;
-
-import java.io.InvalidObjectException;
-import java.io.ObjectStreamException;
-import java.io.Serializable;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.ObjIntConsumer;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Basic implementation of {@code Multiset} backed by an instance of {@code Map}.
- *
- * For serialization to work, the subclass must specify explicit {@code readObject} and {@code
- * writeObject} methods.
- */
-abstract class AbstractMapBasedMultiset extends AbstractMultiset
- implements Serializable {
- // TODO(lowasser): consider overhauling this back to Map
- private transient Map backingMap;
-
- /*
- * Cache the size for efficiency. Using a long lets us avoid the need for
- * overflow checking and ensures that size() will function correctly even if
- * the multiset had once been larger than Integer.MAX_VALUE.
- */
- private transient long size;
-
- /** Standard constructor. */
- protected AbstractMapBasedMultiset(Map backingMap) {
- checkArgument(backingMap.isEmpty());
- this.backingMap = backingMap;
- }
-
- /** Used during deserialization only. The backing map must be empty. */
- void setBackingMap(Map backingMap) {
- this.backingMap = backingMap;
- }
-
- // Required Implementations
-
- /**
- * {@inheritDoc}
- *
- * Invoking {@link Entry#getCount} on an entry in the returned set always returns the
- * current count of that element in the multiset, as opposed to the count at the time the entry
- * was retrieved.
- */
- @Override
- public Set> entrySet() {
- return super.entrySet();
- }
-
- @Override
- Iterator elementIterator() {
- final Iterator> backingEntries = backingMap.entrySet().iterator();
- return new Iterator() {
- @CheckForNull Map.Entry toRemove;
-
- @Override
- public boolean hasNext() {
- return backingEntries.hasNext();
- }
-
- @Override
- @ParametricNullness
- public E next() {
- final Map.Entry mapEntry = backingEntries.next();
- toRemove = mapEntry;
- return mapEntry.getKey();
- }
-
- @Override
- public void remove() {
- checkState(toRemove != null, "no calls to next() since the last call to remove()");
- size -= toRemove.getValue().getAndSet(0);
- backingEntries.remove();
- toRemove = null;
- }
- };
- }
-
- @Override
- Iterator> entryIterator() {
- final Iterator> backingEntries = backingMap.entrySet().iterator();
- return new Iterator>() {
- @CheckForNull Map.Entry toRemove;
-
- @Override
- public boolean hasNext() {
- return backingEntries.hasNext();
- }
-
- @Override
- public Entry next() {
- final Map.Entry mapEntry = backingEntries.next();
- toRemove = mapEntry;
- return new Multisets.AbstractEntry() {
- @Override
- @ParametricNullness
- public E getElement() {
- return mapEntry.getKey();
- }
-
- @Override
- public int getCount() {
- Count count = mapEntry.getValue();
- if (count == null || count.get() == 0) {
- Count frequency = backingMap.get(getElement());
- if (frequency != null) {
- return frequency.get();
- }
- }
- return (count == null) ? 0 : count.get();
- }
- };
- }
-
- @Override
- public void remove() {
- checkState(toRemove != null, "no calls to next() since the last call to remove()");
- size -= toRemove.getValue().getAndSet(0);
- backingEntries.remove();
- toRemove = null;
- }
- };
- }
-
- @Override
- public void forEachEntry(ObjIntConsumer super E> action) {
- checkNotNull(action);
- backingMap.forEach((element, count) -> action.accept(element, count.get()));
- }
-
- @Override
- public void clear() {
- for (Count frequency : backingMap.values()) {
- frequency.set(0);
- }
- backingMap.clear();
- size = 0L;
- }
-
- @Override
- int distinctElements() {
- return backingMap.size();
- }
-
- // Optimizations - Query Operations
-
- @Override
- public int size() {
- return Ints.saturatedCast(size);
- }
-
- @Override
- public Iterator iterator() {
- return new MapBasedMultisetIterator();
- }
-
- /*
- * Not subclassing AbstractMultiset$MultisetIterator because next() needs to
- * retrieve the Map.Entry entry, which can then be used for
- * a more efficient remove() call.
- */
- private class MapBasedMultisetIterator implements Iterator {
- final Iterator> entryIterator;
- @CheckForNull Map.Entry currentEntry;
- int occurrencesLeft;
- boolean canRemove;
-
- MapBasedMultisetIterator() {
- this.entryIterator = backingMap.entrySet().iterator();
- }
-
- @Override
- public boolean hasNext() {
- return occurrencesLeft > 0 || entryIterator.hasNext();
- }
-
- @Override
- @ParametricNullness
- public E next() {
- if (occurrencesLeft == 0) {
- currentEntry = entryIterator.next();
- occurrencesLeft = currentEntry.getValue().get();
- }
- occurrencesLeft--;
- canRemove = true;
- /*
- * requireNonNull is safe because occurrencesLeft starts at 0, forcing us to initialize
- * currentEntry above. After that, we never clear it.
- */
- return requireNonNull(currentEntry).getKey();
- }
-
- @Override
- public void remove() {
- checkRemove(canRemove);
- /*
- * requireNonNull is safe because canRemove is set to true only after we initialize
- * currentEntry (which we never subsequently clear).
- */
- int frequency = requireNonNull(currentEntry).getValue().get();
- if (frequency <= 0) {
- throw new ConcurrentModificationException();
- }
- if (currentEntry.getValue().addAndGet(-1) == 0) {
- entryIterator.remove();
- }
- size--;
- canRemove = false;
- }
- }
-
- @Override
- public int count(@CheckForNull Object element) {
- Count frequency = Maps.safeGet(backingMap, element);
- return (frequency == null) ? 0 : frequency.get();
- }
-
- // Optional Operations - Modification Operations
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalArgumentException if the call would result in more than {@link
- * Integer#MAX_VALUE} occurrences of {@code element} in this multiset.
- */
- @CanIgnoreReturnValue
- @Override
- public int add(@ParametricNullness E element, int occurrences) {
- if (occurrences == 0) {
- return count(element);
- }
- checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
- Count frequency = backingMap.get(element);
- int oldCount;
- if (frequency == null) {
- oldCount = 0;
- backingMap.put(element, new Count(occurrences));
- } else {
- oldCount = frequency.get();
- long newCount = (long) oldCount + (long) occurrences;
- checkArgument(newCount <= Integer.MAX_VALUE, "too many occurrences: %s", newCount);
- frequency.add(occurrences);
- }
- size += occurrences;
- return oldCount;
- }
-
- @CanIgnoreReturnValue
- @Override
- public int remove(@CheckForNull Object element, int occurrences) {
- if (occurrences == 0) {
- return count(element);
- }
- checkArgument(occurrences > 0, "occurrences cannot be negative: %s", occurrences);
- Count frequency = backingMap.get(element);
- if (frequency == null) {
- return 0;
- }
-
- int oldCount = frequency.get();
-
- int numberRemoved;
- if (oldCount > occurrences) {
- numberRemoved = occurrences;
- } else {
- numberRemoved = oldCount;
- backingMap.remove(element);
- }
-
- frequency.add(-numberRemoved);
- size -= numberRemoved;
- return oldCount;
- }
-
- // Roughly a 33% performance improvement over AbstractMultiset.setCount().
- @CanIgnoreReturnValue
- @Override
- public int setCount(@ParametricNullness E element, int count) {
- checkNonnegative(count, "count");
-
- Count existingCounter;
- int oldCount;
- if (count == 0) {
- existingCounter = backingMap.remove(element);
- oldCount = getAndSet(existingCounter, count);
- } else {
- existingCounter = backingMap.get(element);
- oldCount = getAndSet(existingCounter, count);
-
- if (existingCounter == null) {
- backingMap.put(element, new Count(count));
- }
- }
-
- size += (count - oldCount);
- return oldCount;
- }
-
- private static int getAndSet(@CheckForNull Count i, int count) {
- if (i == null) {
- return 0;
- }
-
- return i.getAndSet(count);
- }
-
- // Don't allow default serialization.
- @GwtIncompatible // java.io.ObjectStreamException
- private void readObjectNoData() throws ObjectStreamException {
- throw new InvalidObjectException("Stream data required");
- }
-
- @GwtIncompatible // not needed in emulated source.
- private static final long serialVersionUID = -2250766705698539974L;
-}
diff --git a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMultimap.java b/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMultimap.java
deleted file mode 100644
index f48a6d9..0000000
--- a/datastructures-multi/src/main/java/org/xbib/datastructures/multi/AbstractMultimap.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package org.xbib.datastructures.multi;
-
-import java.util.AbstractCollection;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.Spliterators;
-import org.xbib.datastructures.api.Multimap;
-import org.xbib.datastructures.api.Multiset;
-import org.xbib.datastructures.api.SetMultimap;
-
-/**
- * A skeleton {@code Multimap} implementation, not necessarily in terms of a {@code Map}.
- */
-abstract class AbstractMultimap
- implements Multimap {
- @Override
- public boolean isEmpty() {
- return size() == 0;
- }
-
- @Override
- public boolean containsValue(Object value) {
- for (Collection collection : asMap().values()) {
- if (collection.contains(value)) {
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public boolean containsEntry(Object key, Object value) {
- Collection collection = asMap().get(key);
- return collection != null && collection.contains(value);
- }
-
- @Override
- public boolean remove(Object key, Object value) {
- Collection collection = asMap().get(key);
- return collection != null && collection.remove(value);
- }
-
- @Override
- public boolean put(K key, V value) {
- return get(key).add(value);
- }
-
- @Override
- public boolean putAll(K key, Iterable extends V> values) {
- Objects.requireNonNull(values);
- // make sure we only call values.iterator() once
- // and we only call get(key) if values is nonempty
- if (values instanceof Collection extends V> valueCollection) {
- return !valueCollection.isEmpty() && get(key).addAll(valueCollection);
- } else {
- Iterator extends V> valueItr = values.iterator();
- return valueItr.hasNext() && addAll(get(key), valueItr);
- }
- }
-
- @Override
- public boolean putAll(Multimap extends K, ? extends V> multimap) {
- boolean changed = false;
- for (Entry extends K, ? extends V> entry : multimap.entries()) {
- changed |= put(entry.getKey(), entry.getValue());
- }
- return changed;
- }
-
- @Override
- public Collection replaceValues(K key, Iterable extends V> values) {
- Objects.requireNonNull(values);
- Collection result = removeAll(key);
- putAll(key, values);
- return result;
- }
-
- private transient Collection> entries;
-
- @Override
- public Collection> entries() {
- Collection> result = entries;
- return (result == null) ? entries = createEntries() : result;
- }
-
- abstract Collection> createEntries();
-
- class Entries extends MultimapsEntries {
- @Override
- Multimap multimap() {
- return AbstractMultimap.this;
- }
-
- @Override
- public Iterator