Update #0 - First Release

This commit is contained in:
LAX1DUDE
2022-12-25 01:12:28 -08:00
commit e7179fad45
2154 changed files with 256324 additions and 0 deletions

View File

@ -0,0 +1,441 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
/**
* A general-purpose bimap implementation using any two backing {@code Map}
* instances.
*
* <p>
* Note that this class contains {@code equals()} calls that keep it from
* supporting {@code IdentityHashMap} backing maps.
*
* @author Kevin Bourrillion
* @author Mike Bostock
*/
@GwtCompatible(emulated = true)
abstract class AbstractBiMap<K, V> extends ForwardingMap<K, V> implements BiMap<K, V>, Serializable {
private transient Map<K, V> delegate;
transient AbstractBiMap<V, K> inverse;
/** Package-private constructor for creating a map-backed bimap. */
AbstractBiMap(Map<K, V> forward, Map<V, K> backward) {
setDelegates(forward, backward);
}
/** Private constructor for inverse bimap. */
private AbstractBiMap(Map<K, V> backward, AbstractBiMap<V, K> forward) {
delegate = backward;
inverse = forward;
}
@Override
protected Map<K, V> delegate() {
return delegate;
}
/**
* Returns its input, or throws an exception if this is not a valid key.
*/
K checkKey(@Nullable K key) {
return key;
}
/**
* Returns its input, or throws an exception if this is not a valid value.
*/
V checkValue(@Nullable V value) {
return value;
}
/**
* Specifies the delegate maps going in each direction. Called by the
* constructor and by subclasses during deserialization.
*/
void setDelegates(Map<K, V> forward, Map<V, K> backward) {
checkState(delegate == null);
checkState(inverse == null);
checkArgument(forward.isEmpty());
checkArgument(backward.isEmpty());
checkArgument(forward != backward);
delegate = forward;
inverse = new Inverse<V, K>(backward, this);
}
void setInverse(AbstractBiMap<V, K> inverse) {
this.inverse = inverse;
}
// Query Operations (optimizations)
@Override
public boolean containsValue(@Nullable Object value) {
return inverse.containsKey(value);
}
// Modification Operations
@Override
public V put(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, false);
}
@Override
public V forcePut(@Nullable K key, @Nullable V value) {
return putInBothMaps(key, value, true);
}
private V putInBothMaps(@Nullable K key, @Nullable V value, boolean force) {
checkKey(key);
checkValue(value);
boolean containedKey = containsKey(key);
if (containedKey && Objects.equal(value, get(key))) {
return value;
}
if (force) {
inverse().remove(value);
} else {
checkArgument(!containsValue(value), "value already present: %s", value);
}
V oldValue = delegate.put(key, value);
updateInverseMap(key, containedKey, oldValue, value);
return oldValue;
}
private void updateInverseMap(K key, boolean containedKey, V oldValue, V newValue) {
if (containedKey) {
removeFromInverseMap(oldValue);
}
inverse.delegate.put(newValue, key);
}
@Override
public V remove(@Nullable Object key) {
return containsKey(key) ? removeFromBothMaps(key) : null;
}
private V removeFromBothMaps(Object key) {
V oldValue = delegate.remove(key);
removeFromInverseMap(oldValue);
return oldValue;
}
private void removeFromInverseMap(V oldValue) {
inverse.delegate.remove(oldValue);
}
// Bulk Operations
@Override
public void putAll(Map<? extends K, ? extends V> map) {
for (Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
@Override
public void clear() {
delegate.clear();
inverse.delegate.clear();
}
// Views
@Override
public BiMap<V, K> inverse() {
return inverse;
}
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = new KeySet() : result;
}
private class KeySet extends ForwardingSet<K> {
@Override
protected Set<K> delegate() {
return delegate.keySet();
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object key) {
if (!contains(key)) {
return false;
}
removeFromBothMaps(key);
return true;
}
@Override
public boolean removeAll(Collection<?> keysToRemove) {
return standardRemoveAll(keysToRemove);
}
@Override
public boolean retainAll(Collection<?> keysToRetain) {
return standardRetainAll(keysToRetain);
}
@Override
public Iterator<K> iterator() {
return Maps.keyIterator(entrySet().iterator());
}
}
private transient Set<V> valueSet;
@Override
public Set<V> values() {
/*
* We can almost reuse the inverse's keySet, except we have to fix the iteration
* order so that it is consistent with the forward map.
*/
Set<V> result = valueSet;
return (result == null) ? valueSet = new ValueSet() : result;
}
private class ValueSet extends ForwardingSet<V> {
final Set<V> valuesDelegate = inverse.keySet();
@Override
protected Set<V> delegate() {
return valuesDelegate;
}
@Override
public Iterator<V> iterator() {
return Maps.valueIterator(entrySet().iterator());
}
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public String toString() {
return standardToString();
}
}
private transient Set<Entry<K, V>> entrySet;
@Override
public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> result = entrySet;
return (result == null) ? entrySet = new EntrySet() : result;
}
private class EntrySet extends ForwardingSet<Entry<K, V>> {
final Set<Entry<K, V>> esDelegate = delegate.entrySet();
@Override
protected Set<Entry<K, V>> delegate() {
return esDelegate;
}
@Override
public void clear() {
AbstractBiMap.this.clear();
}
@Override
public boolean remove(Object object) {
if (!esDelegate.contains(object)) {
return false;
}
// safe because esDelgate.contains(object).
Entry<?, ?> entry = (Entry<?, ?>) object;
inverse.delegate.remove(entry.getValue());
/*
* Remove the mapping in inverse before removing from esDelegate because if
* entry is part of esDelegate, entry might be invalidated after the mapping is
* removed from esDelegate.
*/
esDelegate.remove(entry);
return true;
}
@Override
public Iterator<Entry<K, V>> iterator() {
final Iterator<Entry<K, V>> iterator = esDelegate.iterator();
return new Iterator<Entry<K, V>>() {
Entry<K, V> entry;
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Entry<K, V> next() {
entry = iterator.next();
final Entry<K, V> finalEntry = entry;
return new ForwardingMapEntry<K, V>() {
@Override
protected Entry<K, V> delegate() {
return finalEntry;
}
@Override
public V setValue(V value) {
// Preconditions keep the map and inverse consistent.
checkState(contains(this), "entry no longer in map");
// similar to putInBothMaps, but set via entry
if (Objects.equal(value, getValue())) {
return value;
}
checkArgument(!containsValue(value), "value already present: %s", value);
V oldValue = finalEntry.setValue(value);
checkState(Objects.equal(value, get(getKey())), "entry no longer in map");
updateInverseMap(getKey(), true, oldValue, value);
return oldValue;
}
};
}
@Override
public void remove() {
checkRemove(entry != null);
V value = entry.getValue();
iterator.remove();
removeFromInverseMap(value);
}
};
}
// See java.util.Collections.CheckedEntrySet for details on attacks.
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public boolean contains(Object o) {
return Maps.containsEntryImpl(delegate(), o);
}
@Override
public boolean containsAll(Collection<?> c) {
return standardContainsAll(c);
}
@Override
public boolean removeAll(Collection<?> c) {
return standardRemoveAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
return standardRetainAll(c);
}
}
/** The inverse of any other {@code AbstractBiMap} subclass. */
private static class Inverse<K, V> extends AbstractBiMap<K, V> {
private Inverse(Map<K, V> backward, AbstractBiMap<V, K> forward) {
super(backward, forward);
}
/*
* Serialization stores the forward bimap, the inverse of this inverse.
* Deserialization calls inverse() on the forward bimap and returns that
* inverse.
*
* If a bimap and its inverse are serialized together, the deserialized
* instances have inverse() methods that return the other.
*/
@Override
K checkKey(K key) {
return inverse.checkValue(key);
}
@Override
V checkValue(V value) {
return inverse.checkKey(value);
}
/**
* @serialData the forward bimap
*/
@GwtIncompatible("java.io.ObjectOuputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(inverse());
}
@GwtIncompatible("java.io.ObjectInputStream")
@SuppressWarnings("unchecked") // reading data stored by writeObject
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
setInverse((AbstractBiMap<V, K>) stream.readObject());
}
@GwtIncompatible("Not needed in the emulated source.")
Object readResolve() {
return inverse().inverse();
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkPositionIndex;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@link ListIterator}
* interface across a fixed number of elements that may be retrieved by
* position. It does not support {@link #remove}, {@link #set}, or {@link #add}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractIndexedListIterator<E> extends UnmodifiableListIterator<E> {
private final int size;
private int position;
/**
* Returns the element with the specified index. This method is called by
* {@link #next()}.
*/
protected abstract E get(int index);
/**
* Constructs an iterator across a sequence of the given size whose initial
* position is 0. That is, the first call to {@link #next()} will return the
* first element (or throw {@link NoSuchElementException} if {@code size} is
* zero).
*
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size) {
this(size, 0);
}
/**
* Constructs an iterator across a sequence of the given size with the given
* initial position. That is, the first call to {@link #nextIndex()} will return
* {@code position}, and the first call to {@link #next()} will return the
* element at that index, if available. Calls to {@link #previous()} can
* retrieve the preceding {@code position} elements.
*
* @throws IndexOutOfBoundsException if {@code position} is negative or is
* greater than {@code size}
* @throws IllegalArgumentException if {@code size} is negative
*/
protected AbstractIndexedListIterator(int size, int position) {
checkPositionIndex(position, size);
this.size = size;
this.position = position;
}
@Override
public final boolean hasNext() {
return position < size;
}
@Override
public final E next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return get(position++);
}
@Override
public final int nextIndex() {
return position;
}
@Override
public final boolean hasPrevious() {
return position > 0;
}
@Override
public final E previous() {
if (!hasPrevious()) {
throw new NoSuchElementException();
}
return get(--position);
}
@Override
public final int previousIndex() {
return position - 1;
}
}

View File

@ -0,0 +1,189 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkState;
import java.util.NoSuchElementException;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface, to make this interface easier to implement for certain types of
* data sources.
*
* <p>
* {@code Iterator} requires its implementations to support querying the
* end-of-data status without changing the iterator's state, using the
* {@link #hasNext} method. But many data sources, such as
* {@link java.io.Reader#read()}, do not expose this information; the only way
* to discover whether there is any data left is by trying to retrieve it. These
* types of data sources are ordinarily difficult to write iterators for. But
* using this class, one must implement only the {@link #computeNext} method,
* and invoke the {@link #endOfData} method when appropriate.
*
* <p>
* Another example is an iterator that skips over null elements in a backing
* iterator. This could be implemented as:
*
* <pre>
* {@code
*
* public static Iterator<String> skipNulls(final Iterator<String> in) {
* return new AbstractIterator<String>() {
* protected String computeNext() {
* while (in.hasNext()) {
* String s = in.next();
* if (s != null) {
* return s;
* }
* }
* return endOfData();
* }
* };
* }}
* </pre>
*
* <p>
* This class supports iterators that include null elements.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
// When making changes to this class, please also update the copy at
// com.google.common.base.AbstractIterator
@GwtCompatible
public abstract class AbstractIterator<T> extends UnmodifiableIterator<T> {
private State state = State.NOT_READY;
/** Constructor for use by subclasses. */
protected AbstractIterator() {
}
private enum State {
/** We have computed the next element and haven't returned it yet. */
READY,
/** We haven't yet computed or have already returned the element. */
NOT_READY,
/** We have reached the end of the data and are finished. */
DONE,
/** We've suffered an exception and are kaput. */
FAILED,
}
private T next;
/**
* Returns the next element. <b>Note:</b> the implementation must call
* {@link #endOfData()} when there are no elements left in the iteration.
* Failure to do so could result in an infinite loop.
*
* <p>
* The initial invocation of {@link #hasNext()} or {@link #next()} calls this
* method, as does the first invocation of {@code hasNext} or {@code
* next} following each successful call to {@code next}. Once the implementation
* either invokes {@code endOfData} or throws an exception, {@code computeNext}
* is guaranteed to never be called again.
*
* <p>
* If this method throws an exception, it will propagate outward to the
* {@code hasNext} or {@code next} invocation that invoked this method. Any
* further attempts to use the iterator will result in an
* {@link IllegalStateException}.
*
* <p>
* The implementation of this method may not invoke the {@code hasNext},
* {@code next}, or {@link #peek()} methods on this instance; if it does, an
* {@code IllegalStateException} will result.
*
* @return the next element if there was one. If {@code endOfData} was called
* during execution, the return value will be ignored.
* @throws RuntimeException if any unrecoverable error happens. This exception
* will propagate outward to the {@code hasNext()},
* {@code next()}, or {@code peek()} invocation that
* invoked this method. Any further attempts to use the
* iterator will result in an
* {@link IllegalStateException}.
*/
protected abstract T computeNext();
/**
* Implementations of {@link #computeNext} <b>must</b> invoke this method when
* there are no elements left in the iteration.
*
* @return {@code null}; a convenience so your {@code computeNext}
* implementation can use the simple statement
* {@code return endOfData();}
*/
protected final T endOfData() {
state = State.DONE;
return null;
}
@Override
public final boolean hasNext() {
checkState(state != State.FAILED);
switch (state) {
case DONE:
return false;
case READY:
return true;
default:
}
return tryToComputeNext();
}
private boolean tryToComputeNext() {
state = State.FAILED; // temporary pessimism
next = computeNext();
if (state != State.DONE) {
state = State.READY;
return true;
}
return false;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
state = State.NOT_READY;
T result = next;
next = null;
return result;
}
/**
* Returns the next element in the iteration without advancing the iteration,
* according to the contract of {@link PeekingIterator#peek()}.
*
* <p>
* Implementations of {@code AbstractIterator} that wish to expose this
* functionality should implement {@code PeekingIterator}.
*/
public final T peek() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return next;
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link ListMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned
* collections into {@code Lists}. The {@link #createCollection} method must
* return a {@code
* List}.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
abstract class AbstractListMultimap<K, V> extends AbstractMapBasedMultimap<K, V> implements ListMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractListMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract List<V> createCollection();
@Override
List<V> createUnmodifiableEmptyCollection() {
return ImmutableList.of();
}
// Following Javadoc copied from ListMultimap.
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> get(@Nullable K key) {
return (List<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> removeAll(@Nullable Object key) {
return (List<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because the values for a given key may have duplicates and follow the
* insertion ordering, this method returns a {@link List}, instead of the
* {@link Collection} specified in the {@link Multimap} interface.
*/
@Override
public List<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} always
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* {@inheritDoc}
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link List} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>
* Two {@code ListMultimap} instances are equal if, for each key, they contain
* the same values in the same order. If the value orderings disagree, the
* multimaps will not be considered equal.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 6588350623831699109L;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,305 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
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 javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.primitives.Ints;
/**
* Basic implementation of {@code Multiset<E>} backed by an instance of {@code
* Map<E, Count>}.
*
* <p>
* For serialization to work, the subclass must specify explicit {@code
* readObject} and {@code writeObject} methods.
*
* @author Kevin Bourrillion
*/
@GwtCompatible(emulated = true)
abstract class AbstractMapBasedMultiset<E> extends AbstractMultiset<E> implements Serializable {
private transient Map<E, Count> 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<E, Count> backingMap) {
this.backingMap = checkNotNull(backingMap);
this.size = super.size();
}
/** Used during deserialization only. The backing map must be empty. */
void setBackingMap(Map<E, Count> backingMap) {
this.backingMap = backingMap;
}
// Required Implementations
/**
* {@inheritDoc}
*
* <p>
* Invoking {@link Multiset.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<Multiset.Entry<E>> entrySet() {
return super.entrySet();
}
@Override
Iterator<Entry<E>> entryIterator() {
final Iterator<Map.Entry<E, Count>> backingEntries = backingMap.entrySet().iterator();
return new Iterator<Multiset.Entry<E>>() {
Map.Entry<E, Count> toRemove;
@Override
public boolean hasNext() {
return backingEntries.hasNext();
}
@Override
public Multiset.Entry<E> next() {
final Map.Entry<E, Count> mapEntry = backingEntries.next();
toRemove = mapEntry;
return new Multisets.AbstractEntry<E>() {
@Override
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() {
checkRemove(toRemove != null);
size -= toRemove.getValue().getAndSet(0);
backingEntries.remove();
toRemove = null;
}
};
}
@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<E> iterator() {
return new MapBasedMultisetIterator();
}
/*
* Not subclassing AbstractMultiset$MultisetIterator because next() needs to
* retrieve the Map.Entry<E, Count> entry, which can then be used for a more
* efficient remove() call.
*/
private class MapBasedMultisetIterator implements Iterator<E> {
final Iterator<Map.Entry<E, Count>> entryIterator;
Map.Entry<E, Count> currentEntry;
int occurrencesLeft;
boolean canRemove;
MapBasedMultisetIterator() {
this.entryIterator = backingMap.entrySet().iterator();
}
@Override
public boolean hasNext() {
return occurrencesLeft > 0 || entryIterator.hasNext();
}
@Override
public E next() {
if (occurrencesLeft == 0) {
currentEntry = entryIterator.next();
occurrencesLeft = currentEntry.getValue().get();
}
occurrencesLeft--;
canRemove = true;
return currentEntry.getKey();
}
@Override
public void remove() {
checkRemove(canRemove);
int frequency = currentEntry.getValue().get();
if (frequency <= 0) {
throw new ConcurrentModificationException();
}
if (currentEntry.getValue().addAndGet(-1) == 0) {
entryIterator.remove();
}
size--;
canRemove = false;
}
}
@Override
public int count(@Nullable 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.
*/
@Override
public int add(@Nullable 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.getAndAdd(occurrences);
}
size += occurrences;
return oldCount;
}
@Override
public int remove(@Nullable 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.addAndGet(-numberRemoved);
size -= numberRemoved;
return oldCount;
}
// Roughly a 33% performance improvement over AbstractMultiset.setCount().
@Override
public int setCount(@Nullable 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(Count i, int count) {
if (i == null) {
return 0;
}
return i.getAndSet(count);
}
// Don't allow default serialization.
@GwtIncompatible("java.io.ObjectStreamException")
@SuppressWarnings("unused") // actually used during deserialization
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("Stream data required");
}
@GwtIncompatible("not needed in emulated source.")
private static final long serialVersionUID = -2250766705698539974L;
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* Implementation of the {@code equals}, {@code hashCode}, and {@code toString}
* methods of {@code Entry}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractMapEntry<K, V> implements Entry<K, V> {
@Override
public abstract K getKey();
@Override
public abstract V getValue();
@Override
public V setValue(V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue());
}
return false;
}
@Override
public int hashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* Returns a string representation of the form {@code {key}={value}}.
*/
@Override
public String toString() {
return getKey() + "=" + getValue();
}
}

View File

@ -0,0 +1,249 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A skeleton {@code Multimap} implementation, not necessarily in terms of a
* {@code Map}.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultimap<K, V> implements Multimap<K, V> {
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public boolean containsValue(@Nullable Object value) {
for (Collection<V> collection : asMap().values()) {
if (collection.contains(value)) {
return true;
}
}
return false;
}
@Override
public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.contains(value);
}
@Override
public boolean remove(@Nullable Object key, @Nullable Object value) {
Collection<V> collection = asMap().get(key);
return collection != null && collection.remove(value);
}
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return get(key).add(value);
}
@Override
public boolean putAll(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
// make sure we only call values.iterator() once
// and we only call get(key) if values is nonempty
if (values instanceof Collection) {
Collection<? extends V> valueCollection = (Collection<? extends V>) values;
return !valueCollection.isEmpty() && get(key).addAll(valueCollection);
} else {
Iterator<? extends V> valueItr = values.iterator();
return valueItr.hasNext() && Iterators.addAll(get(key), valueItr);
}
}
@Override
public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
boolean changed = false;
for (Map.Entry<? extends K, ? extends V> entry : multimap.entries()) {
changed |= put(entry.getKey(), entry.getValue());
}
return changed;
}
@Override
public Collection<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
checkNotNull(values);
Collection<V> result = removeAll(key);
putAll(key, values);
return result;
}
private transient Collection<Entry<K, V>> entries;
@Override
public Collection<Entry<K, V>> entries() {
Collection<Entry<K, V>> result = entries;
return (result == null) ? entries = createEntries() : result;
}
Collection<Entry<K, V>> createEntries() {
if (this instanceof SetMultimap) {
return new EntrySet();
} else {
return new Entries();
}
}
private class Entries extends Multimaps.Entries<K, V> {
@Override
Multimap<K, V> multimap() {
return AbstractMultimap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
}
private class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
return Sets.hashCodeImpl(this);
}
@Override
public boolean equals(@Nullable Object obj) {
return Sets.equalsImpl(this, obj);
}
}
abstract Iterator<Entry<K, V>> entryIterator();
private transient Set<K> keySet;
@Override
public Set<K> keySet() {
Set<K> result = keySet;
return (result == null) ? keySet = createKeySet() : result;
}
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(asMap());
}
private transient Multiset<K> keys;
@Override
public Multiset<K> keys() {
Multiset<K> result = keys;
return (result == null) ? keys = createKeys() : result;
}
Multiset<K> createKeys() {
return new Multimaps.Keys<K, V>(this);
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valueIterator();
}
@Override
public int size() {
return AbstractMultimap.this.size();
}
@Override
public boolean contains(@Nullable Object o) {
return AbstractMultimap.this.containsValue(o);
}
@Override
public void clear() {
AbstractMultimap.this.clear();
}
}
Iterator<V> valueIterator() {
return Maps.valueIterator(entries().iterator());
}
private transient Map<K, Collection<V>> asMap;
@Override
public Map<K, Collection<V>> asMap() {
Map<K, Collection<V>> result = asMap;
return (result == null) ? asMap = createAsMap() : result;
}
abstract Map<K, Collection<V>> createAsMap();
// Comparison and hashing
@Override
public boolean equals(@Nullable Object object) {
return Multimaps.equalsImpl(this, object);
}
/**
* Returns the hash code for this multimap.
*
* <p>
* The hash code of a multimap is defined as the hash code of the map view, as
* returned by {@link Multimap#asMap}.
*
* @see Map#hashCode
*/
@Override
public int hashCode() {
return asMap().hashCode();
}
/**
* Returns a string representation of the multimap, generated by calling
* {@code toString} on the map returned by {@link Multimap#asMap}.
*
* @return a string representation of the multimap
*/
@Override
public String toString() {
return asMap().toString();
}
}

View File

@ -0,0 +1,241 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.collect.Multisets.setCountImpl;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* This class provides a skeletal implementation of the {@link Multiset}
* interface. A new multiset implementation can be created easily by extending
* this class and implementing the {@link Multiset#entrySet()} method, plus
* optionally overriding {@link #add(Object, int)} and
* {@link #remove(Object, int)} to enable modifications to the multiset.
*
* <p>
* The {@link #count} and {@link #size} implementations all iterate across the
* set returned by {@link Multiset#entrySet()}, as do many methods acting on the
* set returned by {@link #elementSet()}. Override those methods for better
* performance.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractMultiset<E> extends AbstractCollection<E> implements Multiset<E> {
// Query Operations
@Override
public int size() {
return Multisets.sizeImpl(this);
}
@Override
public boolean isEmpty() {
return entrySet().isEmpty();
}
@Override
public boolean contains(@Nullable Object element) {
return count(element) > 0;
}
@Override
public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@Override
public int count(@Nullable Object element) {
for (Entry<E> entry : entrySet()) {
if (Objects.equal(entry.getElement(), element)) {
return entry.getCount();
}
}
return 0;
}
// Modification Operations
@Override
public boolean add(@Nullable E element) {
add(element, 1);
return true;
}
@Override
public int add(@Nullable E element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(@Nullable Object element) {
return remove(element, 1) > 0;
}
@Override
public int remove(@Nullable Object element, int occurrences) {
throw new UnsupportedOperationException();
}
@Override
public int setCount(@Nullable E element, int count) {
return setCountImpl(this, element, count);
}
@Override
public boolean setCount(@Nullable E element, int oldCount, int newCount) {
return setCountImpl(this, element, oldCount, newCount);
}
// Bulk Operations
/**
* {@inheritDoc}
*
* <p>
* This implementation is highly efficient when {@code elementsToAdd} is itself
* a {@link Multiset}.
*/
@Override
public boolean addAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
@Override
public boolean removeAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
@Override
public boolean retainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
@Override
public void clear() {
Iterators.clear(entryIterator());
}
// Views
private transient Set<E> elementSet;
@Override
public Set<E> elementSet() {
Set<E> result = elementSet;
if (result == null) {
elementSet = result = createElementSet();
}
return result;
}
/**
* Creates a new instance of this multiset's element set, which will be returned
* by {@link #elementSet()}.
*/
Set<E> createElementSet() {
return new ElementSet();
}
class ElementSet extends Multisets.ElementSet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
}
abstract Iterator<Entry<E>> entryIterator();
abstract int distinctElements();
private transient Set<Entry<E>> entrySet;
@Override
public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
class EntrySet extends Multisets.EntrySet<E> {
@Override
Multiset<E> multiset() {
return AbstractMultiset.this;
}
@Override
public Iterator<Entry<E>> iterator() {
return entryIterator();
}
@Override
public int size() {
return distinctElements();
}
}
Set<Entry<E>> createEntrySet() {
return new EntrySet();
}
// Object methods
/**
* {@inheritDoc}
*
* <p>
* This implementation returns {@code true} if {@code object} is a multiset of
* the same size and if, for each element, the two multisets have the same
* count.
*/
@Override
public boolean equals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
/**
* {@inheritDoc}
*
* <p>
* This implementation returns the hash code of {@link Multiset#entrySet()}.
*/
@Override
public int hashCode() {
return entrySet().hashCode();
}
/**
* {@inheritDoc}
*
* <p>
* This implementation returns the result of invoking {@code toString} on
* {@link Multiset#entrySet()}.
*/
@Override
public String toString() {
return entrySet().toString();
}
}

View File

@ -0,0 +1,198 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.AbstractMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.SortedMap;
import javax.annotation.Nullable;
/**
* Skeletal implementation of {@link NavigableMap}.
*
* @author Louis Wasserman
*/
abstract class AbstractNavigableMap<K, V> extends AbstractMap<K, V> implements NavigableMap<K, V> {
@Override
@Nullable
public abstract V get(@Nullable Object key);
@Override
@Nullable
public Entry<K, V> firstEntry() {
return Iterators.getNext(entryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> lastEntry() {
return Iterators.getNext(descendingEntryIterator(), null);
}
@Override
@Nullable
public Entry<K, V> pollFirstEntry() {
return Iterators.pollNext(entryIterator());
}
@Override
@Nullable
public Entry<K, V> pollLastEntry() {
return Iterators.pollNext(descendingEntryIterator());
}
@Override
public K firstKey() {
Entry<K, V> entry = firstEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
public K lastKey() {
Entry<K, V> entry = lastEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
@Nullable
public Entry<K, V> lowerEntry(K key) {
return headMap(key, false).lastEntry();
}
@Override
@Nullable
public Entry<K, V> floorEntry(K key) {
return headMap(key, true).lastEntry();
}
@Override
@Nullable
public Entry<K, V> ceilingEntry(K key) {
return tailMap(key, true).firstEntry();
}
@Override
@Nullable
public Entry<K, V> higherEntry(K key) {
return tailMap(key, false).firstEntry();
}
@Override
public K lowerKey(K key) {
return Maps.keyOrNull(lowerEntry(key));
}
@Override
public K floorKey(K key) {
return Maps.keyOrNull(floorEntry(key));
}
@Override
public K ceilingKey(K key) {
return Maps.keyOrNull(ceilingEntry(key));
}
@Override
public K higherKey(K key) {
return Maps.keyOrNull(higherEntry(key));
}
abstract Iterator<Entry<K, V>> entryIterator();
abstract Iterator<Entry<K, V>> descendingEntryIterator();
@Override
public SortedMap<K, V> subMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
@Override
public SortedMap<K, V> headMap(K toKey) {
return headMap(toKey, false);
}
@Override
public SortedMap<K, V> tailMap(K fromKey) {
return tailMap(fromKey, true);
}
@Override
public NavigableSet<K> navigableKeySet() {
return new Maps.NavigableKeySet<K, V>(this);
}
@Override
public Set<K> keySet() {
return navigableKeySet();
}
@Override
public abstract int size();
@Override
public Set<Entry<K, V>> entrySet() {
return new Maps.EntrySet<K, V>() {
@Override
Map<K, V> map() {
return AbstractNavigableMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return entryIterator();
}
};
}
@Override
public NavigableSet<K> descendingKeySet() {
return descendingMap().navigableKeySet();
}
@Override
public NavigableMap<K, V> descendingMap() {
return new DescendingMap();
}
private final class DescendingMap extends Maps.DescendingMap<K, V> {
@Override
NavigableMap<K, V> forward() {
return AbstractNavigableMap.this;
}
@Override
Iterator<Entry<K, V>> entryIterator() {
return descendingEntryIterator();
}
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
/**
* A skeletal implementation of {@code RangeSet}.
*
* @author Louis Wasserman
*/
abstract class AbstractRangeSet<C extends Comparable> implements RangeSet<C> {
AbstractRangeSet() {
}
@Override
public boolean contains(C value) {
return rangeContaining(value) != null;
}
@Override
public abstract Range<C> rangeContaining(C value);
@Override
public boolean isEmpty() {
return asRanges().isEmpty();
}
@Override
public void add(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void remove(Range<C> range) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
remove(Range.<C>all());
}
@Override
public boolean enclosesAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
if (!encloses(range)) {
return false;
}
}
return true;
}
@Override
public void addAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
add(range);
}
}
@Override
public void removeAll(RangeSet<C> other) {
for (Range<C> range : other.asRanges()) {
remove(range);
}
}
@Override
public abstract boolean encloses(Range<C> otherRange);
@Override
public boolean equals(@Nullable Object obj) {
if (obj == this) {
return true;
} else if (obj instanceof RangeSet) {
RangeSet<?> other = (RangeSet<?>) obj;
return this.asRanges().equals(other.asRanges());
}
return false;
}
@Override
public final int hashCode() {
return asRanges().hashCode();
}
@Override
public final String toString() {
return asRanges().toString();
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@code Iterator}
* interface for sequences whose next element can always be derived from the
* previous element. Null elements are not supported, nor is the
* {@link #remove()} method.
*
* <p>
* Example:
*
* <pre>
* {
* &#64;code
*
* Iterator<Integer> powersOfTwo = new AbstractSequentialIterator<Integer>(1) {
* protected Integer computeNext(Integer previous) {
* return (previous == 1 << 30) ? null : previous * 2;
* }
* };
* }
* </pre>
*
* @author Chris Povirk
* @since 12.0 (in Guava as {@code AbstractLinkedIterator} since 8.0)
*/
@GwtCompatible
public abstract class AbstractSequentialIterator<T> extends UnmodifiableIterator<T> {
private T nextOrNull;
/**
* Creates a new iterator with the given first element, or, if {@code
* firstOrNull} is null, creates a new empty iterator.
*/
protected AbstractSequentialIterator(@Nullable T firstOrNull) {
this.nextOrNull = firstOrNull;
}
/**
* Returns the element that follows {@code previous}, or returns {@code null} if
* no elements remain. This method is invoked during each call to
* {@link #next()} in order to compute the result of a <i>future</i> call to
* {@code next()}.
*/
protected abstract T computeNext(T previous);
@Override
public final boolean hasNext() {
return nextOrNull != null;
}
@Override
public final T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return nextOrNull;
} finally {
nextOrNull = computeNext(nextOrNull);
}
}
}

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link SetMultimap} interface. It's a wrapper
* around {@link AbstractMapBasedMultimap} that converts the returned
* collections into {@code Sets}. The {@link #createCollection} method must
* return a {@code Set}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractSetMultimap<K, V> extends AbstractMapBasedMultimap<K, V> implements SetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractSetMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract Set<V> createCollection();
@Override
Set<V> createUnmodifiableEmptyCollection() {
return ImmutableSet.of();
}
// Following Javadoc copied from SetMultimap.
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<V> get(@Nullable K key) {
return (Set<V>) super.get(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<Map.Entry<K, V>> entries() {
return (Set<Map.Entry<K, V>>) super.entries();
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*/
@Override
public Set<V> removeAll(@Nullable Object key) {
return (Set<V>) super.removeAll(key);
}
/**
* {@inheritDoc}
*
* <p>
* Because a {@code SetMultimap} has unique values for a given key, this method
* returns a {@link Set}, instead of the {@link Collection} specified in the
* {@link Multimap} interface.
*
* <p>
* Any duplicates in {@code values} will be stored in the multimap once.
*/
@Override
public Set<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
/**
* {@inheritDoc}
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link Set} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* Stores a key-value pair in the multimap.
*
* @param key key to store in the multimap
* @param value value to store in the multimap
* @return {@code true} if the method increased the size of the multimap, or
* {@code false} if the multimap already contained the key-value pair
*/
@Override
public boolean put(@Nullable K key, @Nullable V value) {
return super.put(key, value);
}
/**
* Compares the specified object to this multimap for equality.
*
* <p>
* Two {@code SetMultimap} instances are equal if, for each key, they contain
* the same values. Equality does not depend on the ordering of keys or values.
*/
@Override
public boolean equals(@Nullable Object object) {
return super.equals(object);
}
private static final long serialVersionUID = 7431625294878419160L;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.SortedMap;
import java.util.SortedSet;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of a {@link SortedSetMultimap} with a sorted key set.
*
* This superclass allows {@code TreeMultimap} to override methods to return
* navigable set and map types in non-GWT only, while GWT code will inherit the
* SortedMap/SortedSet overrides.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractSortedKeySortedSetMultimap<K, V> extends AbstractSortedSetMultimap<K, V> {
AbstractSortedKeySortedSetMultimap(SortedMap<K, Collection<V>> map) {
super(map);
}
@Override
public SortedMap<K, Collection<V>> asMap() {
return (SortedMap<K, Collection<V>>) super.asMap();
}
@Override
SortedMap<K, Collection<V>> backingMap() {
return (SortedMap<K, Collection<V>>) super.backingMap();
}
@Override
public SortedSet<K> keySet() {
return (SortedSet<K>) super.keySet();
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* This class provides a skeletal implementation of the {@link SortedMultiset}
* interface.
*
* <p>
* The {@link #count} and {@link #size} implementations all iterate across the
* set returned by {@link Multiset#entrySet()}, as do many methods acting on the
* set returned by {@link #elementSet()}. Override those methods for better
* performance.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
abstract class AbstractSortedMultiset<E> extends AbstractMultiset<E> implements SortedMultiset<E> {
@GwtTransient
final Comparator<? super E> comparator;
// needed for serialization
@SuppressWarnings("unchecked")
AbstractSortedMultiset() {
this((Comparator) Ordering.natural());
}
AbstractSortedMultiset(Comparator<? super E> comparator) {
this.comparator = checkNotNull(comparator);
}
@Override
public NavigableSet<E> elementSet() {
return (NavigableSet<E>) super.elementSet();
}
@Override
NavigableSet<E> createElementSet() {
return new SortedMultisets.NavigableElementSet<E>(this);
}
@Override
public Comparator<? super E> comparator() {
return comparator;
}
@Override
public Entry<E> firstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> lastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
return entryIterator.hasNext() ? entryIterator.next() : null;
}
@Override
public Entry<E> pollFirstEntry() {
Iterator<Entry<E>> entryIterator = entryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public Entry<E> pollLastEntry() {
Iterator<Entry<E>> entryIterator = descendingEntryIterator();
if (entryIterator.hasNext()) {
Entry<E> result = entryIterator.next();
result = Multisets.immutableEntry(result.getElement(), result.getCount());
entryIterator.remove();
return result;
}
return null;
}
@Override
public SortedMultiset<E> subMultiset(@Nullable E fromElement, BoundType fromBoundType, @Nullable E toElement,
BoundType toBoundType) {
// These are checked elsewhere, but NullPointerTester wants them checked
// eagerly.
checkNotNull(fromBoundType);
checkNotNull(toBoundType);
return tailMultiset(fromElement, fromBoundType).headMultiset(toElement, toBoundType);
}
abstract Iterator<Entry<E>> descendingEntryIterator();
Iterator<E> descendingIterator() {
return Multisets.iteratorImpl(descendingMultiset());
}
private transient SortedMultiset<E> descendingMultiset;
@Override
public SortedMultiset<E> descendingMultiset() {
SortedMultiset<E> result = descendingMultiset;
return (result == null) ? descendingMultiset = createDescendingMultiset() : result;
}
SortedMultiset<E> createDescendingMultiset() {
return new DescendingMultiset<E>() {
@Override
SortedMultiset<E> forwardMultiset() {
return AbstractSortedMultiset.this;
}
@Override
Iterator<Entry<E>> entryIterator() {
return descendingEntryIterator();
}
@Override
public Iterator<E> iterator() {
return descendingIterator();
}
};
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedSet;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Basic implementation of the {@link SortedSetMultimap} interface. It's a
* wrapper around {@link AbstractMapBasedMultimap} that converts the returned
* collections into sorted sets. The {@link #createCollection} method must
* return a {@code SortedSet}.
*
* @author Jared Levy
*/
@GwtCompatible
abstract class AbstractSortedSetMultimap<K, V> extends AbstractSetMultimap<K, V> implements SortedSetMultimap<K, V> {
/**
* Creates a new multimap that uses the provided map.
*
* @param map place to store the mapping from each key to its corresponding
* values
*/
protected AbstractSortedSetMultimap(Map<K, Collection<V>> map) {
super(map);
}
@Override
abstract SortedSet<V> createCollection();
@Override
SortedSet<V> createUnmodifiableEmptyCollection() {
Comparator<? super V> comparator = valueComparator();
if (comparator == null) {
return Collections.unmodifiableSortedSet(createCollection());
} else {
return ImmutableSortedSet.emptySet(valueComparator());
}
}
// Following Javadoc copied from Multimap and SortedSetMultimap.
/**
* Returns a collection view of all values associated with a key. If no mappings
* in the multimap have the provided key, an empty collection is returned.
*
* <p>
* Changes to the returned collection will update the underlying multimap, and
* vice versa.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*/
@Override
public SortedSet<V> get(@Nullable K key) {
return (SortedSet<V>) super.get(key);
}
/**
* Removes all values associated with a given key. The returned collection is
* immutable.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*/
@Override
public SortedSet<V> removeAll(@Nullable Object key) {
return (SortedSet<V>) super.removeAll(key);
}
/**
* Stores a collection of values with the same key, replacing any existing
* values for that key. The returned collection is immutable.
*
* <p>
* Because a {@code SortedSetMultimap} has unique sorted values for a given key,
* this method returns a {@link SortedSet}, instead of the {@link Collection}
* specified in the {@link Multimap} interface.
*
* <p>
* Any duplicates in {@code values} will be stored in the multimap once.
*/
@Override
public SortedSet<V> replaceValues(@Nullable K key, Iterable<? extends V> values) {
return (SortedSet<V>) super.replaceValues(key, values);
}
/**
* Returns a map view that associates each key with the corresponding values in
* the multimap. Changes to the returned map, such as element removal, will
* update the underlying multimap. The map does not support {@code setValue} on
* its entries, {@code put}, or {@code putAll}.
*
* <p>
* When passed a key that is present in the map, {@code
* asMap().get(Object)} has the same behavior as {@link #get}, returning a live
* collection. When passed a key that is not present, however, {@code
* asMap().get(Object)} returns {@code null} instead of an empty collection.
*
* <p>
* Though the method signature doesn't say so explicitly, the returned map has
* {@link SortedSet} values.
*/
@Override
public Map<K, Collection<V>> asMap() {
return super.asMap();
}
/**
* {@inheritDoc}
*
* Consequently, the values do not follow their natural ordering or the ordering
* of the value comparator.
*/
@Override
public Collection<V> values() {
return super.values();
}
private static final long serialVersionUID = 430848587173315748L;
}

View File

@ -0,0 +1,220 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Skeletal, implementation-agnostic implementation of the {@link Table}
* interface.
*
* @author Louis Wasserman
*/
@GwtCompatible
abstract class AbstractTable<R, C, V> implements Table<R, C, V> {
@Override
public boolean containsRow(@Nullable Object rowKey) {
return Maps.safeContainsKey(rowMap(), rowKey);
}
@Override
public boolean containsColumn(@Nullable Object columnKey) {
return Maps.safeContainsKey(columnMap(), columnKey);
}
@Override
public Set<R> rowKeySet() {
return rowMap().keySet();
}
@Override
public Set<C> columnKeySet() {
return columnMap().keySet();
}
@Override
public boolean containsValue(@Nullable Object value) {
for (Map<C, V> row : rowMap().values()) {
if (row.containsValue(value)) {
return true;
}
}
return false;
}
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return row != null && Maps.safeContainsKey(row, columnKey);
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeGet(row, columnKey);
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public void clear() {
Iterators.clear(cellSet().iterator());
}
@Override
public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
Map<C, V> row = Maps.safeGet(rowMap(), rowKey);
return (row == null) ? null : Maps.safeRemove(row, columnKey);
}
@Override
public V put(R rowKey, C columnKey, V value) {
return row(rowKey).put(columnKey, value);
}
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
for (Table.Cell<? extends R, ? extends C, ? extends V> cell : table.cellSet()) {
put(cell.getRowKey(), cell.getColumnKey(), cell.getValue());
}
}
private transient Set<Cell<R, C, V>> cellSet;
@Override
public Set<Cell<R, C, V>> cellSet() {
Set<Cell<R, C, V>> result = cellSet;
return (result == null) ? cellSet = createCellSet() : result;
}
Set<Cell<R, C, V>> createCellSet() {
return new CellSet();
}
abstract Iterator<Table.Cell<R, C, V>> cellIterator();
class CellSet extends AbstractSet<Cell<R, C, V>> {
@Override
public boolean contains(Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Collections2.safeContains(row.entrySet(),
Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof Cell) {
Cell<?, ?, ?> cell = (Cell<?, ?, ?>) o;
Map<C, V> row = Maps.safeGet(rowMap(), cell.getRowKey());
return row != null && Collections2.safeRemove(row.entrySet(),
Maps.immutableEntry(cell.getColumnKey(), cell.getValue()));
}
return false;
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public Iterator<Table.Cell<R, C, V>> iterator() {
return cellIterator();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
private transient Collection<V> values;
@Override
public Collection<V> values() {
Collection<V> result = values;
return (result == null) ? values = createValues() : result;
}
Collection<V> createValues() {
return new Values();
}
Iterator<V> valuesIterator() {
return new TransformedIterator<Cell<R, C, V>, V>(cellSet().iterator()) {
@Override
V transform(Cell<R, C, V> cell) {
return cell.getValue();
}
};
}
class Values extends AbstractCollection<V> {
@Override
public Iterator<V> iterator() {
return valuesIterator();
}
@Override
public boolean contains(Object o) {
return containsValue(o);
}
@Override
public void clear() {
AbstractTable.this.clear();
}
@Override
public int size() {
return AbstractTable.this.size();
}
}
@Override
public boolean equals(@Nullable Object obj) {
return Tables.equalsImpl(this, obj);
}
@Override
public int hashCode() {
return cellSet().hashCode();
}
/**
* Returns the string representation {@code rowMap().toString()}.
*/
@Override
public String toString() {
return rowMap().toString();
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An ordering that treats all references as equals, even nulls.
*
* @author Emily Soldal
*/
@GwtCompatible(serializable = true)
final class AllEqualOrdering extends Ordering<Object> implements Serializable {
static final AllEqualOrdering INSTANCE = new AllEqualOrdering();
@Override
public int compare(@Nullable Object left, @Nullable Object right) {
return 0;
}
@Override
public <E> List<E> sortedCopy(Iterable<E> iterable) {
return Lists.newArrayList(iterable);
}
@Override
public <E> ImmutableList<E> immutableSortedCopy(Iterable<E> iterable) {
return ImmutableList.copyOf(iterable);
}
@SuppressWarnings("unchecked")
@Override
public <S> Ordering<S> reverse() {
return (Ordering<S>) this;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "Ordering.allEqual()";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* Implementation of {@code Multimap} that uses an {@code ArrayList} to store
* the values for a given key. A {@link HashMap} associates each key with an
* {@link ArrayList} of values.
*
* <p>
* When iterating through the collections supplied by this class, the ordering
* of values for a given key agrees with the order in which the values were
* added.
*
* <p>
* This multimap allows duplicate key-value pairs. After adding a new key-value
* pair equal to an existing key-value pair, the {@code
* ArrayListMultimap} will contain entries for both the new value and the old
* value.
*
* <p>
* Keys and values may be null. All optional multimap methods are supported, and
* all returned views are modifiable.
*
* <p>
* The lists returned by {@link #get}, {@link #removeAll}, and
* {@link #replaceValues} all implement {@link net.lax1dude.eaglercraft.v1_8.RandomAccess}.
*
* <p>
* This class is not threadsafe when any concurrent operations update the
* multimap. Concurrent read operations will work correctly. To allow concurrent
* update operations, wrap your multimap with a call to
* {@link Multimaps#synchronizedListMultimap}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap">
* {@code Multimap}</a>.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(serializable = true, emulated = true)
public final class ArrayListMultimap<K, V> extends AbstractListMultimap<K, V> {
// Default from ArrayList
private static final int DEFAULT_VALUES_PER_KEY = 3;
@VisibleForTesting
transient int expectedValuesPerKey;
/**
* Creates a new, empty {@code ArrayListMultimap} with the default initial
* capacities.
*/
public static <K, V> ArrayListMultimap<K, V> create() {
return new ArrayListMultimap<K, V>();
}
/**
* Constructs an empty {@code ArrayListMultimap} with enough capacity to hold
* the specified numbers of keys and values without resizing.
*
* @param expectedKeys the expected number of distinct keys
* @param expectedValuesPerKey the expected average number of values per key
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
public static <K, V> ArrayListMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new ArrayListMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
/**
* Constructs an {@code ArrayListMultimap} with the same mappings as the
* specified multimap.
*
* @param multimap the multimap whose contents are copied to this multimap
*/
public static <K, V> ArrayListMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new ArrayListMultimap<K, V>(multimap);
}
private ArrayListMultimap() {
super(new HashMap<K, Collection<V>>());
expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
}
private ArrayListMultimap(int expectedKeys, int expectedValuesPerKey) {
super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(expectedKeys));
checkNonnegative(expectedValuesPerKey, "expectedValuesPerKey");
this.expectedValuesPerKey = expectedValuesPerKey;
}
private ArrayListMultimap(Multimap<? extends K, ? extends V> multimap) {
this(multimap.keySet().size(),
(multimap instanceof ArrayListMultimap) ? ((ArrayListMultimap<?, ?>) multimap).expectedValuesPerKey
: DEFAULT_VALUES_PER_KEY);
putAll(multimap);
}
/**
* Creates a new, empty {@code ArrayList} to hold the collection of values for
* an arbitrary key.
*/
@Override
List<V> createCollection() {
return new ArrayList<V>(expectedValuesPerKey);
}
/**
* Reduces the memory used by this {@code ArrayListMultimap}, if feasible.
*/
public void trimToSize() {
for (Collection<V> collection : backingMap().values()) {
ArrayList<V> arrayList = (ArrayList<V>) collection;
arrayList.trimToSize();
}
}
/**
* @serialData expectedValuesPerKey, number of distinct keys, and then for each
* distinct key: the key, number of values for that key, and the
* key's values
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(expectedValuesPerKey);
Serialization.writeMultimap(this, stream);
}
@GwtIncompatible("java.io.ObjectOutputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
expectedValuesPerKey = stream.readInt();
int distinctKeys = Serialization.readCount(stream);
Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
setMap(map);
Serialization.populateMultimap(this, stream, distinctKeys);
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,793 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
/**
* Fixed-size {@link Table} implementation backed by a two-dimensional array.
*
* <p>
* The allowed row and column keys must be supplied when the table is created.
* The table always contains a mapping for every row key / column pair. The
* value corresponding to a given row and column is null unless another value is
* provided.
*
* <p>
* The table's size is constant: the product of the number of supplied row keys
* and the number of supplied column keys. The {@code remove} and {@code
* clear} methods are not supported by the table or its views. The
* {@link #erase} and {@link #eraseAll} methods may be used instead.
*
* <p>
* The ordering of the row and column keys provided when the table is
* constructed determines the iteration ordering across rows and columns in the
* table's views. None of the view iterators support {@link Iterator#remove}. If
* the table is modified after an iterator is created, the iterator remains
* valid.
*
* <p>
* This class requires less memory than the {@link HashBasedTable} and
* {@link TreeBasedTable} implementations, except when the table is sparse.
*
* <p>
* Null row keys or column keys are not permitted.
*
* <p>
* This class provides methods involving the underlying array structure, where
* the array indices correspond to the position of a row or column in the lists
* of allowed keys and values. See the {@link #at}, {@link #set},
* {@link #toArray}, {@link #rowKeyList}, and {@link #columnKeyList} methods for
* more details.
*
* <p>
* Note that this implementation is not synchronized. If multiple threads access
* the same cell of an {@code ArrayTable} concurrently and one of the threads
* modifies its value, there is no guarantee that the new value will be fully
* visible to the other threads. To guarantee that modifications are visible,
* synchronize access to the table. Unlike other {@code Table} implementations,
* synchronization is unnecessary between a thread that writes to one cell and a
* thread that reads from another.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
* {@code Table}</a>.
*
* @author Jared Levy
* @since 10.0
*/
@Beta
@GwtCompatible(emulated = true)
public final class ArrayTable<R, C, V> extends AbstractTable<R, C, V> implements Serializable {
/**
* Creates an empty {@code ArrayTable}.
*
* @param rowKeys row keys that may be stored in the generated table
* @param columnKeys column keys that may be stored in the generated table
* @throws NullPointerException if any of the provided keys is null
* @throws IllegalArgumentException if {@code rowKeys} or {@code columnKeys}
* contains duplicates or is empty
*/
public static <R, C, V> ArrayTable<R, C, V> create(Iterable<? extends R> rowKeys,
Iterable<? extends C> columnKeys) {
return new ArrayTable<R, C, V>(rowKeys, columnKeys);
}
/*
* TODO(jlevy): Add factory methods taking an Enum class, instead of an
* iterable, to specify the allowed row keys and/or column keys. Note that
* custom serialization logic is needed to support different enum sizes during
* serialization and deserialization.
*/
/**
* Creates an {@code ArrayTable} with the mappings in the provided table.
*
* <p>
* If {@code table} includes a mapping with row key {@code r} and a separate
* mapping with column key {@code c}, the returned table contains a mapping with
* row key {@code r} and column key {@code c}. If that row key / column key pair
* in not in {@code table}, the pair maps to {@code null} in the generated
* table.
*
* <p>
* The returned table allows subsequent {@code put} calls with the row keys in
* {@code table.rowKeySet()} and the column keys in {@code
* table.columnKeySet()}. Calling {@link #put} with other keys leads to an
* {@code IllegalArgumentException}.
*
* <p>
* The ordering of {@code table.rowKeySet()} and {@code
* table.columnKeySet()} determines the row and column iteration ordering of the
* returned table.
*
* @throws NullPointerException if {@code table} has a null key
* @throws IllegalArgumentException if the provided table is empty
*/
public static <R, C, V> ArrayTable<R, C, V> create(Table<R, C, V> table) {
return (table instanceof ArrayTable<?, ?, ?>) ? new ArrayTable<R, C, V>((ArrayTable<R, C, V>) table)
: new ArrayTable<R, C, V>(table);
}
private final ImmutableList<R> rowList;
private final ImmutableList<C> columnList;
// TODO(jlevy): Add getters returning rowKeyToIndex and columnKeyToIndex?
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final V[][] array;
private ArrayTable(Iterable<? extends R> rowKeys, Iterable<? extends C> columnKeys) {
this.rowList = ImmutableList.copyOf(rowKeys);
this.columnList = ImmutableList.copyOf(columnKeys);
checkArgument(!rowList.isEmpty());
checkArgument(!columnList.isEmpty());
/*
* TODO(jlevy): Support empty rowKeys or columnKeys? If we do, when columnKeys
* is empty but rowKeys isn't, the table is empty but containsRow() can return
* true and rowKeySet() isn't empty.
*/
rowKeyToIndex = index(rowList);
columnKeyToIndex = index(columnList);
@SuppressWarnings("unchecked")
V[][] tmpArray = (V[][]) new Object[rowList.size()][columnList.size()];
array = tmpArray;
// Necessary because in GWT the arrays are initialized with "undefined" instead
// of null.
eraseAll();
}
private static <E> ImmutableMap<E, Integer> index(List<E> list) {
ImmutableMap.Builder<E, Integer> columnBuilder = ImmutableMap.builder();
for (int i = 0; i < list.size(); i++) {
columnBuilder.put(list.get(i), i);
}
return columnBuilder.build();
}
private ArrayTable(Table<R, C, V> table) {
this(table.rowKeySet(), table.columnKeySet());
putAll(table);
}
private ArrayTable(ArrayTable<R, C, V> table) {
rowList = table.rowList;
columnList = table.columnList;
rowKeyToIndex = table.rowKeyToIndex;
columnKeyToIndex = table.columnKeyToIndex;
@SuppressWarnings("unchecked")
V[][] copy = (V[][]) new Object[rowList.size()][columnList.size()];
array = copy;
// Necessary because in GWT the arrays are initialized with "undefined" instead
// of null.
eraseAll();
for (int i = 0; i < rowList.size(); i++) {
System.arraycopy(table.array[i], 0, copy[i], 0, table.array[i].length);
}
}
private abstract static class ArrayMap<K, V> extends Maps.ImprovedAbstractMap<K, V> {
private final ImmutableMap<K, Integer> keyIndex;
private ArrayMap(ImmutableMap<K, Integer> keyIndex) {
this.keyIndex = keyIndex;
}
@Override
public Set<K> keySet() {
return keyIndex.keySet();
}
K getKey(int index) {
return keyIndex.keySet().asList().get(index);
}
abstract String getKeyRole();
@Nullable
abstract V getValue(int index);
@Nullable
abstract V setValue(int index, V newValue);
@Override
public int size() {
return keyIndex.size();
}
@Override
public boolean isEmpty() {
return keyIndex.isEmpty();
}
@Override
protected Set<Entry<K, V>> createEntrySet() {
return new Maps.EntrySet<K, V>() {
@Override
Map<K, V> map() {
return ArrayMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new AbstractIndexedListIterator<Entry<K, V>>(size()) {
@Override
protected Entry<K, V> get(final int index) {
return new AbstractMapEntry<K, V>() {
@Override
public K getKey() {
return ArrayMap.this.getKey(index);
}
@Override
public V getValue() {
return ArrayMap.this.getValue(index);
}
@Override
public V setValue(V value) {
return ArrayMap.this.setValue(index, value);
}
};
}
};
}
};
}
// TODO(user): consider an optimized values() implementation
@Override
public boolean containsKey(@Nullable Object key) {
return keyIndex.containsKey(key);
}
@Override
public V get(@Nullable Object key) {
Integer index = keyIndex.get(key);
if (index == null) {
return null;
} else {
return getValue(index);
}
}
@Override
public V put(K key, V value) {
Integer index = keyIndex.get(key);
if (index == null) {
throw new IllegalArgumentException(getKeyRole() + " " + key + " not in " + keyIndex.keySet());
}
return setValue(index, value);
}
@Override
public V remove(Object key) {
throw new UnsupportedOperationException();
}
@Override
public void clear() {
throw new UnsupportedOperationException();
}
}
/**
* Returns, as an immutable list, the row keys provided when the table was
* constructed, including those that are mapped to null values only.
*/
public ImmutableList<R> rowKeyList() {
return rowList;
}
/**
* Returns, as an immutable list, the column keys provided when the table was
* constructed, including those that are mapped to null values only.
*/
public ImmutableList<C> columnKeyList() {
return columnList;
}
/**
* Returns the value corresponding to the specified row and column indices. The
* same value is returned by {@code
* get(rowKeyList().get(rowIndex), columnKeyList().get(columnIndex))}, but this
* method runs more quickly.
*
* @param rowIndex position of the row key in {@link #rowKeyList()}
* @param columnIndex position of the row key in {@link #columnKeyList()}
* @return the value with the specified row and column
* @throws IndexOutOfBoundsException if either index is negative, {@code
* rowIndex} is greater then or equal to the number of
* allowed row keys, or {@code columnIndex} is
* greater then or equal to the number of
* allowed column keys
*/
public V at(int rowIndex, int columnIndex) {
// In GWT array access never throws IndexOutOfBoundsException.
checkElementIndex(rowIndex, rowList.size());
checkElementIndex(columnIndex, columnList.size());
return array[rowIndex][columnIndex];
}
/**
* Associates {@code value} with the specified row and column indices. The logic
* {@code
* put(rowKeyList().get(rowIndex), columnKeyList().get(columnIndex), value)} has
* the same behavior, but this method runs more quickly.
*
* @param rowIndex position of the row key in {@link #rowKeyList()}
* @param columnIndex position of the row key in {@link #columnKeyList()}
* @param value value to store in the table
* @return the previous value with the specified row and column
* @throws IndexOutOfBoundsException if either index is negative, {@code
* rowIndex} is greater then or equal to the number of
* allowed row keys, or {@code columnIndex} is
* greater then or equal to the number of
* allowed column keys
*/
public V set(int rowIndex, int columnIndex, @Nullable V value) {
// In GWT array access never throws IndexOutOfBoundsException.
checkElementIndex(rowIndex, rowList.size());
checkElementIndex(columnIndex, columnList.size());
V oldValue = array[rowIndex][columnIndex];
array[rowIndex][columnIndex] = value;
return oldValue;
}
/**
* Returns a two-dimensional array with the table contents. The row and column
* indices correspond to the positions of the row and column in the iterables
* provided during table construction. If the table lacks a mapping for a given
* row and column, the corresponding array element is null.
*
* <p>
* Subsequent table changes will not modify the array, and vice versa.
*
* @param valueClass class of values stored in the returned array
*/
@GwtIncompatible("reflection")
public V[][] toArray(Class<V> valueClass) {
// Can change to use varargs in JDK 1.6 if we want
@SuppressWarnings("unchecked") // TODO: safe?
V[][] copy = (V[][]) Array.newInstance(valueClass, new int[] { rowList.size(), columnList.size() });
for (int i = 0; i < rowList.size(); i++) {
System.arraycopy(array[i], 0, copy[i], 0, array[i].length);
}
return copy;
}
/**
* Not supported. Use {@link #eraseAll} instead.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #eraseAll}
*/
@Override
@Deprecated
public void clear() {
throw new UnsupportedOperationException();
}
/**
* Associates the value {@code null} with every pair of allowed row and column
* keys.
*/
public void eraseAll() {
for (V[] row : array) {
Arrays.fill(row, null);
}
}
/**
* Returns {@code true} if the provided keys are among the keys provided when
* the table was constructed.
*/
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return containsRow(rowKey) && containsColumn(columnKey);
}
/**
* Returns {@code true} if the provided column key is among the column keys
* provided when the table was constructed.
*/
@Override
public boolean containsColumn(@Nullable Object columnKey) {
return columnKeyToIndex.containsKey(columnKey);
}
/**
* Returns {@code true} if the provided row key is among the row keys provided
* when the table was constructed.
*/
@Override
public boolean containsRow(@Nullable Object rowKey) {
return rowKeyToIndex.containsKey(rowKey);
}
@Override
public boolean containsValue(@Nullable Object value) {
for (V[] row : array) {
for (V element : row) {
if (Objects.equal(value, element)) {
return true;
}
}
}
return false;
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return (rowIndex == null || columnIndex == null) ? null : at(rowIndex, columnIndex);
}
/**
* Always returns {@code false}.
*/
@Override
public boolean isEmpty() {
return false;
}
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if {@code rowKey} is not in
* {@link #rowKeySet()} or {@code columnKey} is
* not in {@link #columnKeySet()}.
*/
@Override
public V put(R rowKey, C columnKey, @Nullable V value) {
checkNotNull(rowKey);
checkNotNull(columnKey);
Integer rowIndex = rowKeyToIndex.get(rowKey);
checkArgument(rowIndex != null, "Row %s not in %s", rowKey, rowList);
Integer columnIndex = columnKeyToIndex.get(columnKey);
checkArgument(columnIndex != null, "Column %s not in %s", columnKey, columnList);
return set(rowIndex, columnIndex, value);
}
/*
* TODO(jlevy): Consider creating a merge() method, similar to putAll() but
* copying non-null values only.
*/
/**
* {@inheritDoc}
*
* <p>
* If {@code table} is an {@code ArrayTable}, its null values will be stored in
* this table, possibly replacing values that were previously non-null.
*
* @throws NullPointerException if {@code table} has a null key
* @throws IllegalArgumentException if any of the provided table's row keys or
* column keys is not in {@link #rowKeySet()}
* or {@link #columnKeySet()}
*/
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
super.putAll(table);
}
/**
* Not supported. Use {@link #erase} instead.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #erase}
*/
@Override
@Deprecated
public V remove(Object rowKey, Object columnKey) {
throw new UnsupportedOperationException();
}
/**
* Associates the value {@code null} with the specified keys, assuming both keys
* are valid. If either key is null or isn't among the keys provided during
* construction, this method has no effect.
*
* <p>
* This method is equivalent to {@code put(rowKey, columnKey, null)} when both
* provided keys are valid.
*
* @param rowKey row key of mapping to be erased
* @param columnKey column key of mapping to be erased
* @return the value previously associated with the keys, or {@code null} if no
* mapping existed for the keys
*/
public V erase(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
if (rowIndex == null || columnIndex == null) {
return null;
}
return set(rowIndex, columnIndex, null);
}
// TODO(jlevy): Add eraseRow and eraseColumn methods?
@Override
public int size() {
return rowList.size() * columnList.size();
}
/**
* Returns an unmodifiable set of all row key / column key / value triplets.
* Changes to the table will update the returned set.
*
* <p>
* The returned set's iterator traverses the mappings with the first row key,
* the mappings with the second row key, and so on.
*
* <p>
* The value in the returned cells may change if the table subsequently changes.
*
* @return set of table cells consisting of row key / column key / value
* triplets
*/
@Override
public Set<Cell<R, C, V>> cellSet() {
return super.cellSet();
}
@Override
Iterator<Cell<R, C, V>> cellIterator() {
return new AbstractIndexedListIterator<Cell<R, C, V>>(size()) {
@Override
protected Cell<R, C, V> get(final int index) {
return new Tables.AbstractCell<R, C, V>() {
final int rowIndex = index / columnList.size();
final int columnIndex = index % columnList.size();
@Override
public R getRowKey() {
return rowList.get(rowIndex);
}
@Override
public C getColumnKey() {
return columnList.get(columnIndex);
}
@Override
public V getValue() {
return at(rowIndex, columnIndex);
}
};
}
};
}
/**
* Returns a view of all mappings that have the given column key. If the column
* key isn't in {@link #columnKeySet()}, an empty immutable map is returned.
*
* <p>
* Otherwise, for each row key in {@link #rowKeySet()}, the returned map
* associates the row key with the corresponding value in the table. Changes to
* the returned map will update the underlying table, and vice versa.
*
* @param columnKey key of column to search for in the table
* @return the corresponding map from row keys to values
*/
@Override
public Map<R, V> column(C columnKey) {
checkNotNull(columnKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return (columnIndex == null) ? ImmutableMap.<R, V>of() : new Column(columnIndex);
}
private class Column extends ArrayMap<R, V> {
final int columnIndex;
Column(int columnIndex) {
super(rowKeyToIndex);
this.columnIndex = columnIndex;
}
@Override
String getKeyRole() {
return "Row";
}
@Override
V getValue(int index) {
return at(index, columnIndex);
}
@Override
V setValue(int index, V newValue) {
return set(index, columnIndex, newValue);
}
}
/**
* Returns an immutable set of the valid column keys, including those that are
* associated with null values only.
*
* @return immutable set of column keys
*/
@Override
public ImmutableSet<C> columnKeySet() {
return columnKeyToIndex.keySet();
}
private transient ColumnMap columnMap;
@Override
public Map<C, Map<R, V>> columnMap() {
ColumnMap map = columnMap;
return (map == null) ? columnMap = new ColumnMap() : map;
}
private class ColumnMap extends ArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnKeyToIndex);
}
@Override
String getKeyRole() {
return "Column";
}
@Override
Map<R, V> getValue(int index) {
return new Column(index);
}
@Override
Map<R, V> setValue(int index, Map<R, V> newValue) {
throw new UnsupportedOperationException();
}
@Override
public Map<R, V> put(C key, Map<R, V> value) {
throw new UnsupportedOperationException();
}
}
/**
* Returns a view of all mappings that have the given row key. If the row key
* isn't in {@link #rowKeySet()}, an empty immutable map is returned.
*
* <p>
* Otherwise, for each column key in {@link #columnKeySet()}, the returned map
* associates the column key with the corresponding value in the table. Changes
* to the returned map will update the underlying table, and vice versa.
*
* @param rowKey key of row to search for in the table
* @return the corresponding map from column keys to values
*/
@Override
public Map<C, V> row(R rowKey) {
checkNotNull(rowKey);
Integer rowIndex = rowKeyToIndex.get(rowKey);
return (rowIndex == null) ? ImmutableMap.<C, V>of() : new Row(rowIndex);
}
private class Row extends ArrayMap<C, V> {
final int rowIndex;
Row(int rowIndex) {
super(columnKeyToIndex);
this.rowIndex = rowIndex;
}
@Override
String getKeyRole() {
return "Column";
}
@Override
V getValue(int index) {
return at(rowIndex, index);
}
@Override
V setValue(int index, V newValue) {
return set(rowIndex, index, newValue);
}
}
/**
* Returns an immutable set of the valid row keys, including those that are
* associated with null values only.
*
* @return immutable set of row keys
*/
@Override
public ImmutableSet<R> rowKeySet() {
return rowKeyToIndex.keySet();
}
private transient RowMap rowMap;
@Override
public Map<R, Map<C, V>> rowMap() {
RowMap map = rowMap;
return (map == null) ? rowMap = new RowMap() : map;
}
private class RowMap extends ArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowKeyToIndex);
}
@Override
String getKeyRole() {
return "Row";
}
@Override
Map<C, V> getValue(int index) {
return new Row(index);
}
@Override
Map<C, V> setValue(int index, Map<C, V> newValue) {
throw new UnsupportedOperationException();
}
@Override
public Map<C, V> put(R key, Map<C, V> value) {
throw new UnsupportedOperationException();
}
}
/**
* Returns an unmodifiable collection of all values, which may contain
* duplicates. Changes to the table will update the returned collection.
*
* <p>
* The returned collection's iterator traverses the values of the first row key,
* the values of the second row key, and so on.
*
* @return collection of values
*/
@Override
public Collection<V> values() {
return super.values();
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A bimap (or "bidirectional map") is a map that preserves the uniqueness of
* its values as well as that of its keys. This constraint enables bimaps to
* support an "inverse view", which is another bimap containing the same entries
* as this bimap but with reversed keys and values.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface BiMap<K, V> extends Map<K, V> {
// Modification Operations
/**
* {@inheritDoc}
*
* @throws IllegalArgumentException if the given value is already bound to a
* different key in this bimap. The bimap will
* remain unmodified in this event. To avoid
* this exception, call {@link #forcePut}
* instead.
*/
@Override
V put(@Nullable K key, @Nullable V value);
/**
* An alternate form of {@code put} that silently removes any existing entry
* with the value {@code value} before proceeding with the {@link #put}
* operation. If the bimap previously contained the provided key-value mapping,
* this method has no effect.
*
* <p>
* Note that a successful call to this method could cause the size of the bimap
* to increase by one, stay the same, or even decrease by one.
*
* <p>
* <b>Warning:</b> If an existing entry with this value is removed, the key for
* that entry is discarded and not returned.
*
* @param key the key with which the specified value is to be associated
* @param value the value to be associated with the specified key
* @return the value which was previously associated with the key, which may be
* {@code null}, or {@code null} if there was no previous entry
*/
V forcePut(@Nullable K key, @Nullable V value);
// Bulk Operations
/**
* {@inheritDoc}
*
* <p>
* <b>Warning:</b> the results of calling this method may vary depending on the
* iteration order of {@code map}.
*
* @throws IllegalArgumentException if an attempt to {@code put} any entry
* fails. Note that some map entries may have
* been added to the bimap before the exception
* was thrown.
*/
@Override
void putAll(Map<? extends K, ? extends V> map);
// Views
/**
* {@inheritDoc}
*
* <p>
* Because a bimap has unique values, this method returns a {@link Set}, instead
* of the {@link java.util.Collection} specified in the {@link Map} interface.
*/
@Override
Set<V> values();
/**
* Returns the inverse view of this bimap, which maps each of this bimap's
* values to its associated key. The two bimaps are backed by the same data; any
* changes to one will appear in the other.
*
* <p>
* <b>Note:</b>There is no guaranteed correspondence between the iteration order
* of a bimap and that of its inverse.
*
* @return the inverse view of this bimap
*/
BiMap<V, K> inverse();
}

View File

@ -0,0 +1,213 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.Deque;
import java.util.Iterator;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Optional;
/**
* A variant of {@link TreeTraverser} for binary trees, providing additional
* traversals specific to binary trees.
*
* @author Louis Wasserman
* @since 15.0
*/
@Beta
@GwtCompatible(emulated = true)
public abstract class BinaryTreeTraverser<T> extends TreeTraverser<T> {
// TODO(user): make this GWT-compatible when we've checked in ArrayDeque and
// BitSet emulation
/**
* Returns the left child of the specified node, or {@link Optional#absent()} if
* the specified node has no left child.
*/
public abstract Optional<T> leftChild(T root);
/**
* Returns the right child of the specified node, or {@link Optional#absent()}
* if the specified node has no right child.
*/
public abstract Optional<T> rightChild(T root);
/**
* Returns the children of this node, in left-to-right order.
*/
@Override
public final Iterable<T> children(final T root) {
checkNotNull(root);
return new FluentIterable<T>() {
@Override
public Iterator<T> iterator() {
return new AbstractIterator<T>() {
boolean doneLeft;
boolean doneRight;
@Override
protected T computeNext() {
if (!doneLeft) {
doneLeft = true;
Optional<T> left = leftChild(root);
if (left.isPresent()) {
return left.get();
}
}
if (!doneRight) {
doneRight = true;
Optional<T> right = rightChild(root);
if (right.isPresent()) {
return right.get();
}
}
return endOfData();
}
};
}
};
}
@Override
UnmodifiableIterator<T> preOrderIterator(T root) {
return new PreOrderIterator(root);
}
/*
* Optimized implementation of preOrderIterator for binary trees.
*/
private final class PreOrderIterator extends UnmodifiableIterator<T> implements PeekingIterator<T> {
private final Deque<T> stack;
PreOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
stack.addLast(root);
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public T next() {
T result = stack.removeLast();
pushIfPresent(stack, rightChild(result));
pushIfPresent(stack, leftChild(result));
return result;
}
@Override
public T peek() {
return stack.getLast();
}
}
@Override
UnmodifiableIterator<T> postOrderIterator(T root) {
return new PostOrderIterator(root);
}
/*
* Optimized implementation of postOrderIterator for binary trees.
*/
private final class PostOrderIterator extends UnmodifiableIterator<T> {
private final Deque<T> stack;
private final BitSet hasExpanded;
PostOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
stack.addLast(root);
this.hasExpanded = new BitSet();
}
@Override
public boolean hasNext() {
return !stack.isEmpty();
}
@Override
public T next() {
while (true) {
T node = stack.getLast();
boolean expandedNode = hasExpanded.get(stack.size() - 1);
if (expandedNode) {
stack.removeLast();
hasExpanded.clear(stack.size());
return node;
} else {
hasExpanded.set(stack.size() - 1);
pushIfPresent(stack, rightChild(node));
pushIfPresent(stack, leftChild(node));
}
}
}
}
// TODO(user): see if any significant optimizations are possible for
// breadthFirstIterator
public final FluentIterable<T> inOrderTraversal(final T root) {
checkNotNull(root);
return new FluentIterable<T>() {
@Override
public UnmodifiableIterator<T> iterator() {
return new InOrderIterator(root);
}
};
}
private final class InOrderIterator extends AbstractIterator<T> {
private final Deque<T> stack;
private final BitSet hasExpandedLeft;
InOrderIterator(T root) {
this.stack = new ArrayDeque<T>();
this.hasExpandedLeft = new BitSet();
stack.addLast(root);
}
@Override
protected T computeNext() {
while (!stack.isEmpty()) {
T node = stack.getLast();
if (hasExpandedLeft.get(stack.size() - 1)) {
stack.removeLast();
hasExpandedLeft.clear(stack.size());
pushIfPresent(stack, rightChild(node));
return node;
} else {
hasExpandedLeft.set(stack.size() - 1);
pushIfPresent(stack, leftChild(node));
}
}
return endOfData();
}
}
private static <T> void pushIfPresent(Deque<T> stack, Optional<T> node) {
if (node.isPresent()) {
stack.addLast(node.get());
}
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Indicates whether an endpoint of some range is contained in the range itself
* ("closed") or not ("open"). If a range is unbounded on a side, it is neither
* open nor closed on that side; the bound simply does not exist.
*
* @since 10.0
*/
@GwtCompatible
public enum BoundType {
/**
* The endpoint value <i>is not</i> considered part of the set ("exclusive").
*/
OPEN {
@Override
BoundType flip() {
return CLOSED;
}
},
/**
* The endpoint value <i>is</i> considered part of the set ("inclusive").
*/
CLOSED {
@Override
BoundType flip() {
return OPEN;
}
};
/**
* Returns the bound type corresponding to a boolean value for inclusivity.
*/
static BoundType forBoolean(boolean inclusive) {
return inclusive ? CLOSED : OPEN;
}
abstract BoundType flip();
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Objects;
/**
* An ordering that orders elements by applying an order to the result of a
* function on those elements.
*/
@GwtCompatible(serializable = true)
final class ByFunctionOrdering<F, T> extends Ordering<F> implements Serializable {
final Function<F, ? extends T> function;
final Ordering<T> ordering;
ByFunctionOrdering(Function<F, ? extends T> function, Ordering<T> ordering) {
this.function = checkNotNull(function);
this.ordering = checkNotNull(ordering);
}
@Override
public int compare(F left, F right) {
return ordering.compare(function.apply(left), function.apply(right));
}
@Override
public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
if (object instanceof ByFunctionOrdering) {
ByFunctionOrdering<?, ?> that = (ByFunctionOrdering<?, ?>) object;
return this.function.equals(that.function) && this.ordering.equals(that.ordering);
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(function, ordering);
}
@Override
public String toString() {
return ordering + ".onResultOf(" + function + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkElementIndex;
import java.util.AbstractList;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.math.IntMath;
/**
* Implementation of {@link Lists#cartesianProduct(List)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class CartesianList<E> extends AbstractList<List<E>> implements RandomAccess {
private transient final ImmutableList<List<E>> axes;
private transient final int[] axesSizeProduct;
static <E> List<List<E>> create(List<? extends List<? extends E>> lists) {
ImmutableList.Builder<List<E>> axesBuilder = new ImmutableList.Builder<List<E>>(lists.size());
for (List<? extends E> list : lists) {
List<E> copy = ImmutableList.copyOf(list);
if (copy.isEmpty()) {
return ImmutableList.of();
}
axesBuilder.add(copy);
}
return new CartesianList<E>(axesBuilder.build());
}
CartesianList(ImmutableList<List<E>> axes) {
this.axes = axes;
int[] axesSizeProduct = new int[axes.size() + 1];
axesSizeProduct[axes.size()] = 1;
try {
for (int i = axes.size() - 1; i >= 0; i--) {
axesSizeProduct[i] = IntMath.checkedMultiply(axesSizeProduct[i + 1], axes.get(i).size());
}
} catch (ArithmeticException e) {
throw new IllegalArgumentException("Cartesian product too large; must have size at most Integer.MAX_VALUE");
}
this.axesSizeProduct = axesSizeProduct;
}
private int getAxisIndexForProductIndex(int index, int axis) {
return (index / axesSizeProduct[axis + 1]) % axes.get(axis).size();
}
@Override
public ImmutableList<E> get(final int index) {
checkElementIndex(index, size());
return new ImmutableList<E>() {
@Override
public int size() {
return axes.size();
}
@Override
public E get(int axis) {
checkElementIndex(axis, size());
int axisIndex = getAxisIndexForProductIndex(index, axis);
return axes.get(axis).get(axisIndex);
}
@Override
boolean isPartialView() {
return true;
}
};
}
@Override
public int size() {
return axesSizeProduct[0];
}
@Override
public boolean contains(@Nullable Object o) {
if (!(o instanceof List)) {
return false;
}
List<?> list = (List<?>) o;
if (list.size() != axes.size()) {
return false;
}
ListIterator<?> itr = list.listIterator();
while (itr.hasNext()) {
int index = itr.nextIndex();
if (!axes.get(index).contains(itr.next())) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,68 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A map, each entry of which maps a Java
* <a href="http://tinyurl.com/2cmwkz">raw type</a> to an instance of that type.
* In addition to implementing {@code Map}, the additional type-safe operations
* {@link #putInstance} and {@link #getInstance} are available.
*
* <p>
* Like any other {@code Map<Class, Object>}, this map may contain entries for
* primitive types, and a primitive type and its corresponding wrapper type may
* map to different values.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#ClassToInstanceMap">
* {@code ClassToInstanceMap}</a>.
*
* <p>
* To map a generic type to an instance of that type, use
* {@link com.google.common.reflect.TypeToInstanceMap} instead.
*
* @param <B> the common supertype that all entries must share; often this is
* simply {@link Object}
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public interface ClassToInstanceMap<B> extends Map<Class<? extends B>, B> {
/**
* Returns the value the specified class is mapped to, or {@code null} if no
* entry for this class is present. This will only return a value that was bound
* to this specific class, not a value that may have been bound to a subtype.
*/
<T extends B> T getInstance(Class<T> type);
/**
* Maps the specified class to the specified value. Does <i>not</i> associate
* this value with any of the class's supertypes.
*
* @return the value previously associated with this class (possibly {@code
* null}), or {@code null} if there was no previous entry.
*/
<T extends B> T putInstance(Class<T> type, @Nullable T value);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.annotations.GwtCompatible;
/**
* Precondition checks useful in collection implementations.
*/
@GwtCompatible
final class CollectPreconditions {
static void checkEntryNotNull(Object key, Object value) {
if (key == null) {
throw new NullPointerException("null key in entry: null=" + value);
} else if (value == null) {
throw new NullPointerException("null value in entry: " + key + "=null");
}
}
static int checkNonnegative(int value, String name) {
if (value < 0) {
throw new IllegalArgumentException(name + " cannot be negative but was: " + value);
}
return value;
}
/**
* Precondition tester for {@code Iterator.remove()} that throws an exception
* with a consistent error message.
*/
static void checkRemove(boolean canRemove) {
checkState(canRemove, "no calls to next() since the last call to remove()");
}
}

View File

@ -0,0 +1,695 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.math.LongMath.binomial;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.math.IntMath;
import com.google.common.primitives.Ints;
/**
* Provides static methods for working with {@code Collection} instances.
*
* @author Chris Povirk
* @author Mike Bostock
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public final class Collections2 {
private Collections2() {
}
/**
* Returns the elements of {@code unfiltered} that satisfy a predicate. The
* returned collection is a live view of {@code unfiltered}; changes to one
* affect the other.
*
* <p>
* The resulting collection's iterator does not support {@code remove()}, but
* all other collection methods are supported. When given an element that
* doesn't satisfy the predicate, the collection's {@code add()} and {@code
* addAll()} methods throw an {@link IllegalArgumentException}. When methods
* such as {@code removeAll()} and {@code clear()} are called on the filtered
* collection, only elements that satisfy the filter will be removed from the
* underlying collection.
*
* <p>
* The returned collection isn't threadsafe or serializable, even if
* {@code unfiltered} is.
*
* <p>
* Many of the filtered collection's methods, such as {@code size()}, iterate
* across every element in the underlying collection and determine which
* elements satisfy the filter. When a live view is <i>not</i> needed, it may be
* faster to copy {@code Iterables.filter(unfiltered, predicate)} and use the
* copy.
*
* <p>
* <b>Warning:</b> {@code predicate} must be <i>consistent with equals</i>, as
* documented at {@link Predicate#apply}. Do not provide a predicate such as
* {@code Predicates.instanceOf(ArrayList.class)}, which is inconsistent with
* equals. (See {@link Iterables#filter(Iterable, Class)} for related
* functionality.)
*/
// TODO(kevinb): how can we omit that Iterables link when building gwt
// javadoc?
public static <E> Collection<E> filter(Collection<E> unfiltered, Predicate<? super E> predicate) {
if (unfiltered instanceof FilteredCollection) {
// Support clear(), removeAll(), and retainAll() when filtering a filtered
// collection.
return ((FilteredCollection<E>) unfiltered).createCombined(predicate);
}
return new FilteredCollection<E>(checkNotNull(unfiltered), checkNotNull(predicate));
}
/**
* Delegates to {@link Collection#contains}. Returns {@code false} if the
* {@code contains} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeContains(Collection<?> collection, @Nullable Object object) {
checkNotNull(collection);
try {
return collection.contains(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* Delegates to {@link Collection#remove}. Returns {@code false} if the
* {@code remove} method throws a {@code ClassCastException} or
* {@code NullPointerException}.
*/
static boolean safeRemove(Collection<?> collection, @Nullable Object object) {
checkNotNull(collection);
try {
return collection.remove(object);
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
static class FilteredCollection<E> extends AbstractCollection<E> {
final Collection<E> unfiltered;
final Predicate<? super E> predicate;
FilteredCollection(Collection<E> unfiltered, Predicate<? super E> predicate) {
this.unfiltered = unfiltered;
this.predicate = predicate;
}
FilteredCollection<E> createCombined(Predicate<? super E> newPredicate) {
return new FilteredCollection<E>(unfiltered, Predicates.<E>and(predicate, newPredicate));
// .<E> above needed to compile in JDK 5
}
@Override
public boolean add(E element) {
checkArgument(predicate.apply(element));
return unfiltered.add(element);
}
@Override
public boolean addAll(Collection<? extends E> collection) {
for (E element : collection) {
checkArgument(predicate.apply(element));
}
return unfiltered.addAll(collection);
}
@Override
public void clear() {
Iterables.removeIf(unfiltered, predicate);
}
@Override
public boolean contains(@Nullable Object element) {
if (safeContains(unfiltered, element)) {
@SuppressWarnings("unchecked") // element is in unfiltered, so it must be an E
E e = (E) element;
return predicate.apply(e);
}
return false;
}
@Override
public boolean containsAll(Collection<?> collection) {
return containsAllImpl(this, collection);
}
@Override
public boolean isEmpty() {
return !Iterables.any(unfiltered, predicate);
}
@Override
public Iterator<E> iterator() {
return Iterators.filter(unfiltered.iterator(), predicate);
}
@Override
public boolean remove(Object element) {
return contains(element) && unfiltered.remove(element);
}
@Override
public boolean removeAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, (Predicate<E>)in(collection)));
}
@Override
public boolean retainAll(final Collection<?> collection) {
return Iterables.removeIf(unfiltered, and(predicate, (Predicate<E>)not(in(collection))));
}
@Override
public int size() {
return Iterators.size(iterator());
}
@Override
public Object[] toArray() {
// creating an ArrayList so filtering happens once
return Lists.newArrayList(iterator()).toArray();
}
@Override
public <T> T[] toArray(T[] array) {
return Lists.newArrayList(iterator()).toArray(array);
}
}
/**
* Returns a collection that applies {@code function} to each element of
* {@code fromCollection}. The returned collection is a live view of {@code
* fromCollection}; changes to one affect the other.
*
* <p>
* The returned collection's {@code add()} and {@code addAll()} methods throw an
* {@link UnsupportedOperationException}. All other collection methods are
* supported, as long as {@code fromCollection} supports them.
*
* <p>
* The returned collection isn't threadsafe or serializable, even if
* {@code fromCollection} is.
*
* <p>
* When a live view is <i>not</i> needed, it may be faster to copy the
* transformed collection and use the copy.
*
* <p>
* If the input {@code Collection} is known to be a {@code List}, consider
* {@link Lists#transform}. If only an {@code Iterable} is available, use
* {@link Iterables#transform}.
*/
public static <F, T> Collection<T> transform(Collection<F> fromCollection, Function<? super F, T> function) {
return new TransformedCollection<F, T>(fromCollection, function);
}
static class TransformedCollection<F, T> extends AbstractCollection<T> {
final Collection<F> fromCollection;
final Function<? super F, ? extends T> function;
TransformedCollection(Collection<F> fromCollection, Function<? super F, ? extends T> function) {
this.fromCollection = checkNotNull(fromCollection);
this.function = checkNotNull(function);
}
@Override
public void clear() {
fromCollection.clear();
}
@Override
public boolean isEmpty() {
return fromCollection.isEmpty();
}
@Override
public Iterator<T> iterator() {
return Iterators.transform(fromCollection.iterator(), function);
}
@Override
public int size() {
return fromCollection.size();
}
}
/**
* Returns {@code true} if the collection {@code self} contains all of the
* elements in the collection {@code c}.
*
* <p>
* This method iterates over the specified collection {@code c}, checking each
* element returned by the iterator in turn to see if it is contained in the
* specified collection {@code self}. If all elements are so contained,
* {@code true} is returned, otherwise {@code false}.
*
* @param self a collection which might contain all elements in {@code c}
* @param c a collection whose elements might be contained by {@code self}
*/
static boolean containsAllImpl(Collection<?> self, Collection<?> c) {
return Iterables.all(c, Predicates.in(self));
}
/**
* An implementation of {@link Collection#toString()}.
*/
static String toStringImpl(final Collection<?> collection) {
StringBuilder sb = newStringBuilderForCollection(collection.size()).append('[');
STANDARD_JOINER.appendTo(sb, Iterables.transform(collection, new Function<Object, Object>() {
@Override
public Object apply(Object input) {
return input == collection ? "(this Collection)" : input;
}
}));
return sb.append(']').toString();
}
/**
* Returns best-effort-sized StringBuilder based on the given collection size.
*/
static StringBuilder newStringBuilderForCollection(int size) {
checkNonnegative(size, "size");
return new StringBuilder((int) Math.min(size * 8L, Ints.MAX_POWER_OF_TWO));
}
/**
* Used to avoid http://bugs.sun.com/view_bug.do?bug_id=6558557
*/
static <T> Collection<T> cast(Iterable<T> iterable) {
return (Collection<T>) iterable;
}
static final Joiner STANDARD_JOINER = Joiner.on(", ").useForNull("null");
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable}.
*
* <p>
* <i>Notes:</i> This is an implementation of the algorithm for Lexicographical
* Permutations Generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2. The iteration order
* follows the lexicographical order. This means that the first permutation will
* be in ascending order, and the last will be in descending order.
*
* <p>
* Duplicate elements are considered equal. For example, the list [1, 1] will
* have only one permutation, instead of two. This is why the elements have to
* implement {@link Comparable}.
*
* <p>
* An empty iterable has only one permutation, which is an empty list.
*
* <p>
* This method is equivalent to
* {@code Collections2.orderedPermutations(list, Ordering.natural())}.
*
* @param elements the original iterable whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException if the specified iterable is null or has any
* null elements.
* @since 12.0
*/
@Beta
public static <E extends Comparable<? super E>> Collection<List<E>> orderedPermutations(Iterable<E> elements) {
return orderedPermutations(elements, Ordering.natural());
}
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Iterable} using the specified {@link Comparator} for establishing the
* lexicographical ordering.
*
* <p>
* Examples:
*
* <pre>
* {@code
*
* for (List<String> perm : orderedPermutations(asList("b", "c", "a"))) {
* println(perm);
* }
* // -> ["a", "b", "c"]
* // -> ["a", "c", "b"]
* // -> ["b", "a", "c"]
* // -> ["b", "c", "a"]
* // -> ["c", "a", "b"]
* // -> ["c", "b", "a"]
*
* for (List<Integer> perm : orderedPermutations(asList(1, 2, 2, 1))) {
* println(perm);
* }
* // -> [1, 1, 2, 2]
* // -> [1, 2, 1, 2]
* // -> [1, 2, 2, 1]
* // -> [2, 1, 1, 2]
* // -> [2, 1, 2, 1]
* // -> [2, 2, 1, 1]}
* </pre>
*
* <p>
* <i>Notes:</i> This is an implementation of the algorithm for Lexicographical
* Permutations Generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2. The iteration order
* follows the lexicographical order. This means that the first permutation will
* be in ascending order, and the last will be in descending order.
*
* <p>
* Elements that compare equal are considered equal and no new permutations are
* created by swapping them.
*
* <p>
* An empty iterable has only one permutation, which is an empty list.
*
* @param elements the original iterable whose elements have to be permuted.
* @param comparator a comparator for the iterable's elements.
* @return an immutable {@link Collection} containing all the different
* permutations of the original iterable.
* @throws NullPointerException If the specified iterable is null, has any null
* elements, or if the specified comparator is
* null.
* @since 12.0
*/
@Beta
public static <E> Collection<List<E>> orderedPermutations(Iterable<E> elements, Comparator<? super E> comparator) {
return new OrderedPermutationCollection<E>(elements, comparator);
}
private static final class OrderedPermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
final Comparator<? super E> comparator;
final int size;
OrderedPermutationCollection(Iterable<E> input, Comparator<? super E> comparator) {
this.inputList = Ordering.from(comparator).immutableSortedCopy(input);
this.comparator = comparator;
this.size = calculateSize(inputList, comparator);
}
/**
* The number of permutations with repeated elements is calculated as follows:
* <ul>
* <li>For an empty list, it is 1 (base case).</li>
* <li>When r numbers are added to a list of n-r elements, the number of
* permutations is increased by a factor of (n choose r).</li>
* </ul>
*/
private static <E> int calculateSize(List<E> sortedInputList, Comparator<? super E> comparator) {
long permutations = 1;
int n = 1;
int r = 1;
while (n < sortedInputList.size()) {
int comparison = comparator.compare(sortedInputList.get(n - 1), sortedInputList.get(n));
if (comparison < 0) {
// We move to the next non-repeated element.
permutations *= binomial(n, r);
r = 0;
if (!isPositiveInt(permutations)) {
return Integer.MAX_VALUE;
}
}
n++;
r++;
}
permutations *= binomial(n, r);
if (!isPositiveInt(permutations)) {
return Integer.MAX_VALUE;
}
return (int) permutations;
}
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Iterator<List<E>> iterator() {
return new OrderedPermutationIterator<E>(inputList, comparator);
}
@Override
public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
}
return false;
}
@Override
public String toString() {
return "orderedPermutationCollection(" + inputList + ")";
}
}
private static final class OrderedPermutationIterator<E> extends AbstractIterator<List<E>> {
List<E> nextPermutation;
final Comparator<? super E> comparator;
OrderedPermutationIterator(List<E> list, Comparator<? super E> comparator) {
this.nextPermutation = Lists.newArrayList(list);
this.comparator = comparator;
}
@Override
protected List<E> computeNext() {
if (nextPermutation == null) {
return endOfData();
}
ImmutableList<E> next = ImmutableList.copyOf(nextPermutation);
calculateNextPermutation();
return next;
}
void calculateNextPermutation() {
int j = findNextJ();
if (j == -1) {
nextPermutation = null;
return;
}
int l = findNextL(j);
Collections.swap(nextPermutation, j, l);
int n = nextPermutation.size();
Collections.reverse(nextPermutation.subList(j + 1, n));
}
int findNextJ() {
for (int k = nextPermutation.size() - 2; k >= 0; k--) {
if (comparator.compare(nextPermutation.get(k), nextPermutation.get(k + 1)) < 0) {
return k;
}
}
return -1;
}
int findNextL(int j) {
E ak = nextPermutation.get(j);
for (int l = nextPermutation.size() - 1; l > j; l--) {
if (comparator.compare(ak, nextPermutation.get(l)) < 0) {
return l;
}
}
throw new AssertionError("this statement should be unreachable");
}
}
/**
* Returns a {@link Collection} of all the permutations of the specified
* {@link Collection}.
*
* <p>
* <i>Notes:</i> This is an implementation of the Plain Changes algorithm for
* permutations generation, described in Knuth's "The Art of Computer
* Programming", Volume 4, Chapter 7, Section 7.2.1.2.
*
* <p>
* If the input list contains equal elements, some of the generated permutations
* will be equal.
*
* <p>
* An empty collection has only one permutation, which is an empty list.
*
* @param elements the original collection whose elements have to be permuted.
* @return an immutable {@link Collection} containing all the different
* permutations of the original collection.
* @throws NullPointerException if the specified collection is null or has any
* null elements.
* @since 12.0
*/
@Beta
public static <E> Collection<List<E>> permutations(Collection<E> elements) {
return new PermutationCollection<E>(ImmutableList.copyOf(elements));
}
private static final class PermutationCollection<E> extends AbstractCollection<List<E>> {
final ImmutableList<E> inputList;
PermutationCollection(ImmutableList<E> input) {
this.inputList = input;
}
@Override
public int size() {
return IntMath.factorial(inputList.size());
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public Iterator<List<E>> iterator() {
return new PermutationIterator<E>(inputList);
}
@Override
public boolean contains(@Nullable Object obj) {
if (obj instanceof List) {
List<?> list = (List<?>) obj;
return isPermutation(inputList, list);
}
return false;
}
@Override
public String toString() {
return "permutations(" + inputList + ")";
}
}
private static class PermutationIterator<E> extends AbstractIterator<List<E>> {
final List<E> list;
final int[] c;
final int[] o;
int j;
PermutationIterator(List<E> list) {
this.list = new ArrayList<E>(list);
int n = list.size();
c = new int[n];
o = new int[n];
Arrays.fill(c, 0);
Arrays.fill(o, 1);
j = Integer.MAX_VALUE;
}
@Override
protected List<E> computeNext() {
if (j <= 0) {
return endOfData();
}
ImmutableList<E> next = ImmutableList.copyOf(list);
calculateNextPermutation();
return next;
}
void calculateNextPermutation() {
j = list.size() - 1;
int s = 0;
// Handle the special case of an empty list. Skip the calculation of the
// next permutation.
if (j == -1) {
return;
}
while (true) {
int q = c[j] + o[j];
if (q < 0) {
switchDirection();
continue;
}
if (q == j + 1) {
if (j == 0) {
break;
}
s++;
switchDirection();
continue;
}
Collections.swap(list, j - c[j] + s, j - q + s);
c[j] = q;
break;
}
}
void switchDirection() {
o[j] = -o[j];
j--;
}
}
/**
* Returns {@code true} if the second list is a permutation of the first.
*/
private static boolean isPermutation(List<?> first, List<?> second) {
if (first.size() != second.size()) {
return false;
}
Multiset<?> firstMultiset = HashMultiset.create(first);
Multiset<?> secondMultiset = HashMultiset.create(second);
return firstMultiset.equals(secondMultiset);
}
private static boolean isPositiveInt(long n) {
return n >= 0 && n <= Integer.MAX_VALUE;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/** An ordering for a pre-existing comparator. */
@GwtCompatible(serializable = true)
final class ComparatorOrdering<T> extends Ordering<T> implements Serializable {
final Comparator<T> comparator;
ComparatorOrdering(Comparator<T> comparator) {
this.comparator = checkNotNull(comparator);
}
@Override
public int compare(T a, T b) {
return comparator.compare(a, b);
}
@Override
public boolean equals(@Nullable Object object) {
if (object == this) {
return true;
}
if (object instanceof ComparatorOrdering) {
ComparatorOrdering<?> that = (ComparatorOrdering<?>) object;
return this.comparator.equals(that.comparator);
}
return false;
}
@Override
public int hashCode() {
return comparator.hashCode();
}
@Override
public String toString() {
return comparator.toString();
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,253 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.primitives.Booleans;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
/**
* A utility for performing a chained comparison statement. For example:
*
* <pre>
* {@code
*
* public int compareTo(Foo that) {
* return ComparisonChain.start()
* .compare(this.aString, that.aString)
* .compare(this.anInt, that.anInt)
* .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
* .result();
* }}
* </pre>
*
* <p>
* The value of this expression will have the same sign as the <i>first
* nonzero</i> comparison result in the chain, or will be zero if every
* comparison result was zero.
*
* <p>
* Performance note: Even though the {@code ComparisonChain} caller always
* invokes its {@code compare} methods unconditionally, the {@code
* ComparisonChain} implementation stops calling its inputs'
* {@link Comparable#compareTo compareTo} and {@link Comparator#compare compare}
* methods as soon as one of them returns a nonzero result. This optimization is
* typically important only in the presence of expensive {@code compareTo} and
* {@code compare} implementations.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/CommonObjectUtilitiesExplained#compare/compareTo">
* {@code ComparisonChain}</a>.
*
* @author Mark Davis
* @author Kevin Bourrillion
* @since 2.0
*/
@GwtCompatible
public abstract class ComparisonChain {
private ComparisonChain() {
}
/**
* Begins a new chained comparison statement. See example in the class
* documentation.
*/
public static ComparisonChain start() {
return ACTIVE;
}
private static final ComparisonChain ACTIVE = new ComparisonChain() {
@SuppressWarnings("unchecked")
@Override
public ComparisonChain compare(Comparable left, Comparable right) {
return classify(left.compareTo(right));
}
@Override
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator<T> comparator) {
return classify(comparator.compare(left, right));
}
@Override
public ComparisonChain compare(int left, int right) {
return classify(Ints.compare(left, right));
}
@Override
public ComparisonChain compare(long left, long right) {
return classify(Longs.compare(left, right));
}
@Override
public ComparisonChain compare(float left, float right) {
return classify(Float.compare(left, right));
}
@Override
public ComparisonChain compare(double left, double right) {
return classify(Double.compare(left, right));
}
@Override
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return classify(Booleans.compare(right, left)); // reversed
}
@Override
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return classify(Booleans.compare(left, right));
}
ComparisonChain classify(int result) {
return (result < 0) ? LESS : (result > 0) ? GREATER : ACTIVE;
}
@Override
public int result() {
return 0;
}
};
private static final ComparisonChain LESS = new InactiveComparisonChain(-1);
private static final ComparisonChain GREATER = new InactiveComparisonChain(1);
private static final class InactiveComparisonChain extends ComparisonChain {
final int result;
InactiveComparisonChain(int result) {
this.result = result;
}
@Override
public ComparisonChain compare(@Nullable Comparable left, @Nullable Comparable right) {
return this;
}
@Override
public <T> ComparisonChain compare(@Nullable T left, @Nullable T right, @Nullable Comparator<T> comparator) {
return this;
}
@Override
public ComparisonChain compare(int left, int right) {
return this;
}
@Override
public ComparisonChain compare(long left, long right) {
return this;
}
@Override
public ComparisonChain compare(float left, float right) {
return this;
}
@Override
public ComparisonChain compare(double left, double right) {
return this;
}
@Override
public ComparisonChain compareTrueFirst(boolean left, boolean right) {
return this;
}
@Override
public ComparisonChain compareFalseFirst(boolean left, boolean right) {
return this;
}
@Override
public int result() {
return result;
}
}
/**
* Compares two comparable objects as specified by {@link Comparable#compareTo},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(Comparable<?> left, Comparable<?> right);
/**
* Compares two objects using a comparator, <i>if</i> the result of this
* comparison chain has not already been determined.
*/
public abstract <T> ComparisonChain compare(@Nullable T left, @Nullable T right, Comparator<T> comparator);
/**
* Compares two {@code int} values as specified by {@link Ints#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(int left, int right);
/**
* Compares two {@code long} values as specified by {@link Longs#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(long left, long right);
/**
* Compares two {@code float} values as specified by {@link Float#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(float left, float right);
/**
* Compares two {@code double} values as specified by {@link Double#compare},
* <i>if</i> the result of this comparison chain has not already been
* determined.
*/
public abstract ComparisonChain compare(double left, double right);
/**
* Compares two {@code boolean} values, considering {@code true} to be less than
* {@code false}, <i>if</i> the result of this comparison chain has not already
* been determined.
*
* @since 12.0
*/
public abstract ComparisonChain compareTrueFirst(boolean left, boolean right);
/**
* Compares two {@code boolean} values, considering {@code false} to be less
* than {@code true}, <i>if</i> the result of this comparison chain has not
* already been determined.
*
* @since 12.0 (present as {@code compare} since 2.0)
*/
public abstract ComparisonChain compareFalseFirst(boolean left, boolean right);
/**
* Ends this comparison chain and returns its result: a value having the same
* sign as the first nonzero comparison result in the chain, or zero if every
* result was zero.
*/
public abstract int result();
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import java.util.Comparator;
import com.google.common.annotations.GwtCompatible;
/** An ordering that tries several comparators in order. */
@GwtCompatible(serializable = true)
final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableList<Comparator<? super T>> comparators;
CompoundOrdering(Comparator<? super T> primary, Comparator<? super T> secondary) {
this.comparators = ImmutableList.<Comparator<? super T>>of(primary, secondary);
}
CompoundOrdering(Iterable<? extends Comparator<? super T>> comparators) {
this.comparators = ImmutableList.copyOf(comparators);
}
@Override
public int compare(T left, T right) {
// Avoid using the Iterator to avoid generating garbage (issue 979).
int size = comparators.size();
for (int i = 0; i < size; i++) {
int result = comparators.get(i).compare(left, right);
if (result != 0) {
return result;
}
}
return 0;
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof CompoundOrdering) {
CompoundOrdering<?> that = (CompoundOrdering<?>) object;
return this.comparators.equals(that.comparators);
}
return false;
}
@Override
public int hashCode() {
return comparators.hashCode();
}
@Override
public String toString() {
return "Ordering.compound(" + comparators + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Wraps an exception that occurred during a computation.
*
* @author Bob Lee
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public class ComputationException extends RuntimeException {
/**
* Creates a new instance with the given cause.
*/
public ComputationException(@Nullable Throwable cause) {
super(cause);
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* A constraint that an element must satisfy in order to be added to a
* collection. For example, {@link Constraints#notNull()}, which prevents a
* collection from including any null elements, could be implemented like this:
*
* <pre>
* {@code
*
* public Object checkElement(Object element) {
* if (element == null) {
* throw new NullPointerException();
* }
* return element;
* }}
* </pre>
*
* <p>
* In order to be effective, constraints should be deterministic; that is, they
* should not depend on state that can change (such as external state, random
* variables, and time) and should only depend on the value of the passed-in
* element. A non-deterministic constraint cannot reliably enforce that all the
* collection's elements meet the constraint, since the constraint is only
* enforced when elements are added.
*
* @author Mike Bostock
*/
@GwtCompatible
interface Constraint<E> {
/**
* Throws a suitable {@code RuntimeException} if the specified element is
* illegal. Typically this is either a {@link NullPointerException}, an
* {@link IllegalArgumentException}, or a {@link ClassCastException}, though an
* application-specific exception class may be used if appropriate.
*
* @param element the element to check
* @return the provided element
*/
E checkElement(E element);
/**
* Returns a brief human readable description of this constraint, such as "Not
* null" or "Positive number".
*/
@Override
String toString();
}

View File

@ -0,0 +1,340 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import java.util.Set;
import java.util.SortedSet;
import com.google.common.annotations.GwtCompatible;
/**
* Factories and utilities pertaining to the {@link Constraint} interface.
*
* @author Mike Bostock
* @author Jared Levy
*/
@GwtCompatible
final class Constraints {
private Constraints() {
}
/**
* Returns a constrained view of the specified collection, using the specified
* constraint. Any operations that add new elements to the collection will call
* the provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned collection is not serializable.
*
* @param collection the collection to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the collection
*/
public static <E> Collection<E> constrainedCollection(Collection<E> collection, Constraint<? super E> constraint) {
return new ConstrainedCollection<E>(collection, constraint);
}
/** @see Constraints#constrainedCollection */
static class ConstrainedCollection<E> extends ForwardingCollection<E> {
private final Collection<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedCollection(Collection<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected Collection<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified set, using the specified
* constraint. Any operations that add new elements to the set will call the
* provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned set is not serializable.
*
* @param set the set to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the set
*/
public static <E> Set<E> constrainedSet(Set<E> set, Constraint<? super E> constraint) {
return new ConstrainedSet<E>(set, constraint);
}
/** @see Constraints#constrainedSet */
static class ConstrainedSet<E> extends ForwardingSet<E> {
private final Set<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedSet(Set<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected Set<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified sorted set, using the specified
* constraint. Any operations that add new elements to the sorted set will call
* the provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* The returned set is not serializable.
*
* @param sortedSet the sorted set to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the sorted set
*/
public static <E> SortedSet<E> constrainedSortedSet(SortedSet<E> sortedSet, Constraint<? super E> constraint) {
return new ConstrainedSortedSet<E>(sortedSet, constraint);
}
/** @see Constraints#constrainedSortedSet */
private static class ConstrainedSortedSet<E> extends ForwardingSortedSet<E> {
final SortedSet<E> delegate;
final Constraint<? super E> constraint;
ConstrainedSortedSet(SortedSet<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected SortedSet<E> delegate() {
return delegate;
}
@Override
public SortedSet<E> headSet(E toElement) {
return constrainedSortedSet(delegate.headSet(toElement), constraint);
}
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
return constrainedSortedSet(delegate.subSet(fromElement, toElement), constraint);
}
@Override
public SortedSet<E> tailSet(E fromElement) {
return constrainedSortedSet(delegate.tailSet(fromElement), constraint);
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
}
/**
* Returns a constrained view of the specified list, using the specified
* constraint. Any operations that add new elements to the list will call the
* provided constraint. However, this method does not verify that existing
* elements satisfy the constraint.
*
* <p>
* If {@code list} implements {@link RandomAccess}, so will the returned list.
* The returned list is not serializable.
*
* @param list the list to constrain
* @param constraint the constraint that validates added elements
* @return a constrained view of the list
*/
public static <E> List<E> constrainedList(List<E> list, Constraint<? super E> constraint) {
return (list instanceof RandomAccess) ? new ConstrainedRandomAccessList<E>(list, constraint)
: new ConstrainedList<E>(list, constraint);
}
/** @see Constraints#constrainedList */
@GwtCompatible
private static class ConstrainedList<E> extends ForwardingList<E> {
final List<E> delegate;
final Constraint<? super E> constraint;
ConstrainedList(List<E> delegate, Constraint<? super E> constraint) {
this.delegate = checkNotNull(delegate);
this.constraint = checkNotNull(constraint);
}
@Override
protected List<E> delegate() {
return delegate;
}
@Override
public boolean add(E element) {
constraint.checkElement(element);
return delegate.add(element);
}
@Override
public void add(int index, E element) {
constraint.checkElement(element);
delegate.add(index, element);
}
@Override
public boolean addAll(Collection<? extends E> elements) {
return delegate.addAll(checkElements(elements, constraint));
}
@Override
public boolean addAll(int index, Collection<? extends E> elements) {
return delegate.addAll(index, checkElements(elements, constraint));
}
@Override
public ListIterator<E> listIterator() {
return constrainedListIterator(delegate.listIterator(), constraint);
}
@Override
public ListIterator<E> listIterator(int index) {
return constrainedListIterator(delegate.listIterator(index), constraint);
}
@Override
public E set(int index, E element) {
constraint.checkElement(element);
return delegate.set(index, element);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return constrainedList(delegate.subList(fromIndex, toIndex), constraint);
}
}
/** @see Constraints#constrainedList */
static class ConstrainedRandomAccessList<E> extends ConstrainedList<E> implements RandomAccess {
ConstrainedRandomAccessList(List<E> delegate, Constraint<? super E> constraint) {
super(delegate, constraint);
}
}
/**
* Returns a constrained view of the specified list iterator, using the
* specified constraint. Any operations that would add new elements to the
* underlying list will be verified by the constraint.
*
* @param listIterator the iterator for which to return a constrained view
* @param constraint the constraint for elements in the list
* @return a constrained view of the specified iterator
*/
private static <E> ListIterator<E> constrainedListIterator(ListIterator<E> listIterator,
Constraint<? super E> constraint) {
return new ConstrainedListIterator<E>(listIterator, constraint);
}
/** @see Constraints#constrainedListIterator */
static class ConstrainedListIterator<E> extends ForwardingListIterator<E> {
private final ListIterator<E> delegate;
private final Constraint<? super E> constraint;
public ConstrainedListIterator(ListIterator<E> delegate, Constraint<? super E> constraint) {
this.delegate = delegate;
this.constraint = constraint;
}
@Override
protected ListIterator<E> delegate() {
return delegate;
}
@Override
public void add(E element) {
constraint.checkElement(element);
delegate.add(element);
}
@Override
public void set(E element) {
constraint.checkElement(element);
delegate.set(element);
}
}
static <E> Collection<E> constrainedTypePreservingCollection(Collection<E> collection, Constraint<E> constraint) {
if (collection instanceof SortedSet) {
return constrainedSortedSet((SortedSet<E>) collection, constraint);
} else if (collection instanceof Set) {
return constrainedSet((Set<E>) collection, constraint);
} else if (collection instanceof List) {
return constrainedList((List<E>) collection, constraint);
} else {
return constrainedCollection(collection, constraint);
}
}
/*
* TODO(kevinb): For better performance, avoid making a copy of the elements by
* having addAll() call add() repeatedly instead.
*/
private static <E> Collection<E> checkElements(Collection<E> elements, Constraint<? super E> constraint) {
Collection<E> copy = Lists.newArrayList(elements);
for (E element : copy) {
constraint.checkElement(element);
}
return copy;
}
}

View File

@ -0,0 +1,199 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.NoSuchElementException;
import java.util.Set;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A sorted set of contiguous values in a given {@link DiscreteDomain}.
*
* <p>
* <b>Warning:</b> Be extremely careful what you do with conceptually large
* instances (such as
* {@code ContiguousSet.create(Range.greaterThan(0), DiscreteDomain.integers()}).
* Certain operations on such a set can be performed efficiently, but others
* (such as {@link Set#hashCode} or {@link Collections#frequency}) can cause
* major performance problems.
*
* @author Gregory Kick
* @since 10.0
*/
@Beta
@GwtCompatible(emulated = true)
@SuppressWarnings("rawtypes") // allow ungenerified Comparable types
public abstract class ContiguousSet<C extends Comparable> extends ImmutableSortedSet<C> {
/**
* Returns a {@code ContiguousSet} containing the same values in the given
* domain {@linkplain Range#contains contained} by the range.
*
* @throws IllegalArgumentException if neither range nor the domain has a lower
* bound, or if neither has an upper bound
*
* @since 13.0
*/
public static <C extends Comparable> ContiguousSet<C> create(Range<C> range, DiscreteDomain<C> domain) {
checkNotNull(range);
checkNotNull(domain);
Range<C> effectiveRange = range;
try {
if (!range.hasLowerBound()) {
effectiveRange = effectiveRange.intersection(Range.atLeast(domain.minValue()));
}
if (!range.hasUpperBound()) {
effectiveRange = effectiveRange.intersection(Range.atMost(domain.maxValue()));
}
} catch (NoSuchElementException e) {
throw new IllegalArgumentException(e);
}
// Per class spec, we are allowed to throw CCE if necessary
boolean empty = effectiveRange.isEmpty() || Range.compareOrThrow(range.lowerBound.leastValueAbove(domain),
range.upperBound.greatestValueBelow(domain)) > 0;
return empty ? new EmptyContiguousSet<C>(domain) : new RegularContiguousSet<C>(effectiveRange, domain);
}
final DiscreteDomain<C> domain;
ContiguousSet(DiscreteDomain<C> domain) {
super(Ordering.natural());
this.domain = domain;
}
@Override
public ContiguousSet<C> headSet(C toElement) {
return headSetImpl(checkNotNull(toElement), false);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> headSet(C toElement, boolean inclusive) {
return headSetImpl(checkNotNull(toElement), inclusive);
}
@Override
public ContiguousSet<C> subSet(C fromElement, C toElement) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, true, toElement, false);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> subSet(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
checkNotNull(fromElement);
checkNotNull(toElement);
checkArgument(comparator().compare(fromElement, toElement) <= 0);
return subSetImpl(fromElement, fromInclusive, toElement, toInclusive);
}
@Override
public ContiguousSet<C> tailSet(C fromElement) {
return tailSetImpl(checkNotNull(fromElement), true);
}
/**
* @since 12.0
*/
@GwtIncompatible("NavigableSet")
@Override
public ContiguousSet<C> tailSet(C fromElement, boolean inclusive) {
return tailSetImpl(checkNotNull(fromElement), inclusive);
}
/*
* These methods perform most headSet, subSet, and tailSet logic, besides
* parameter validation.
*/
/* @Override */ abstract ContiguousSet<C> headSetImpl(C toElement, boolean inclusive);
/* @Override */ abstract ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
boolean toInclusive);
/* @Override */ abstract ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive);
/**
* Returns the set of values that are contained in both this set and the other.
*
* <p>
* This method should always be used instead of {@link Sets#intersection} for
* {@link ContiguousSet} instances.
*/
public abstract ContiguousSet<C> intersection(ContiguousSet<C> other);
/**
* Returns a range, closed on both ends, whose endpoints are the minimum and
* maximum values contained in this set. This is equivalent to
* {@code range(CLOSED, CLOSED)}.
*
* @throws NoSuchElementException if this set is empty
*/
public abstract Range<C> range();
/**
* Returns the minimal range with the given boundary types for which all values
* in this set are {@linkplain Range#contains(Comparable) contained} within the
* range.
*
* <p>
* Note that this method will return ranges with unbounded endpoints if
* {@link BoundType#OPEN} is requested for a domain minimum or maximum. For
* example, if {@code set} was created from the range
* {@code [1..Integer.MAX_VALUE]} then {@code set.range(CLOSED, OPEN)} must
* return {@code [1..∞)}.
*
* @throws NoSuchElementException if this set is empty
*/
public abstract Range<C> range(BoundType lowerBoundType, BoundType upperBoundType);
/**
* Returns a short-hand representation of the contents such as
* {@code "[1..100]"}.
*/
@Override
public String toString() {
return range().toString();
}
/**
* Not supported. {@code ContiguousSet} instances are constructed with
* {@link #create}. This method exists only to hide {@link ImmutableSet#builder}
* from consumers of {@code
* ContiguousSet}.
*
* @throws UnsupportedOperationException always
* @deprecated Use {@link #create}.
*/
@Deprecated
public static <E> ImmutableSortedSet.Builder<E> builder() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A mutable value of type {@code int}, for multisets to use in tracking counts
* of values.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class Count implements Serializable {
private int value;
Count(int value) {
this.value = value;
}
public int get() {
return value;
}
public int getAndAdd(int delta) {
int result = value;
value = result + delta;
return result;
}
public int addAndGet(int delta) {
return value += delta;
}
public void set(int newValue) {
value = newValue;
}
public int getAndSet(int newValue) {
int result = value;
value = newValue;
return result;
}
@Override
public int hashCode() {
return value;
}
@Override
public boolean equals(@Nullable Object obj) {
return obj instanceof Count && ((Count) obj).value == value;
}
@Override
public String toString() {
return Integer.toString(value);
}
}

View File

@ -0,0 +1,459 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.NoSuchElementException;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.primitives.Booleans;
/**
* Implementation detail for the internal structure of {@link Range} instances.
* Represents a unique way of "cutting" a "number line" (actually of instances
* of type {@code C}, not necessarily "numbers") into two sections; this can be
* done below a certain value, above a certain value, below all values or above
* all values. With this object defined in this way, an interval can always be
* represented by a pair of {@code Cut} instances.
*
* @author Kevin Bourrillion
*/
@GwtCompatible
abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializable {
final C endpoint;
Cut(@Nullable C endpoint) {
this.endpoint = endpoint;
}
abstract boolean isLessThan(C value);
abstract BoundType typeAsLowerBound();
abstract BoundType typeAsUpperBound();
abstract Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain);
abstract Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain);
abstract void describeAsLowerBound(StringBuilder sb);
abstract void describeAsUpperBound(StringBuilder sb);
abstract C leastValueAbove(DiscreteDomain<C> domain);
abstract C greatestValueBelow(DiscreteDomain<C> domain);
/*
* The canonical form is a BelowValue cut whenever possible, otherwise
* ABOVE_ALL, or (only in the case of types that are unbounded below) BELOW_ALL.
*/
Cut<C> canonical(DiscreteDomain<C> domain) {
return this;
}
// note: overriden by {BELOW,ABOVE}_ALL
@Override
public int compareTo(Cut<C> that) {
if (that == belowAll()) {
return 1;
}
if (that == aboveAll()) {
return -1;
}
int result = Range.compareOrThrow(endpoint, that.endpoint);
if (result != 0) {
return result;
}
// same value. below comes before above
return Booleans.compare(this instanceof AboveValue, that instanceof AboveValue);
}
C endpoint() {
return endpoint;
}
@SuppressWarnings("unchecked") // catching CCE
@Override
public boolean equals(Object obj) {
if (obj instanceof Cut) {
// It might not really be a Cut<C>, but we'll catch a CCE if it's not
Cut<C> that = (Cut<C>) obj;
try {
int compareResult = compareTo(that);
return compareResult == 0;
} catch (ClassCastException ignored) {
}
}
return false;
}
/*
* The implementation neither produces nor consumes any non-null instance of
* type C, so casting the type parameter is safe.
*/
@SuppressWarnings("unchecked")
static <C extends Comparable> Cut<C> belowAll() {
return (Cut<C>) BelowAll.INSTANCE;
}
private static final long serialVersionUID = 0;
private static final class BelowAll extends Cut<Comparable<?>> {
private static final BelowAll INSTANCE = new BelowAll();
private BelowAll() {
super(null);
}
@Override
Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
@Override
boolean isLessThan(Comparable<?> value) {
return true;
}
@Override
BoundType typeAsLowerBound() {
throw new IllegalStateException();
}
@Override
BoundType typeAsUpperBound() {
throw new AssertionError("this statement should be unreachable");
}
@Override
Cut<Comparable<?>> withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
@Override
Cut<Comparable<?>> withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append("(-\u221e");
}
@Override
void describeAsUpperBound(StringBuilder sb) {
throw new AssertionError();
}
@Override
Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
return domain.minValue();
}
@Override
Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
@Override
Cut<Comparable<?>> canonical(DiscreteDomain<Comparable<?>> domain) {
try {
return Cut.<Comparable<?>>belowValue(domain.minValue());
} catch (NoSuchElementException e) {
return this;
}
}
@Override
public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : -1;
}
@Override
public String toString() {
return "-\u221e";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}
/*
* The implementation neither produces nor consumes any non-null instance of
* type C, so casting the type parameter is safe.
*/
@SuppressWarnings("unchecked")
static <C extends Comparable> Cut<C> aboveAll() {
return (Cut<C>) AboveAll.INSTANCE;
}
private static final class AboveAll extends Cut<Comparable<?>> {
private static final AboveAll INSTANCE = new AboveAll();
private AboveAll() {
super(null);
}
@Override
Comparable<?> endpoint() {
throw new IllegalStateException("range unbounded on this side");
}
@Override
boolean isLessThan(Comparable<?> value) {
return false;
}
@Override
BoundType typeAsLowerBound() {
throw new AssertionError("this statement should be unreachable");
}
@Override
BoundType typeAsUpperBound() {
throw new IllegalStateException();
}
@Override
Cut<Comparable<?>> withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError("this statement should be unreachable");
}
@Override
Cut<Comparable<?>> withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain) {
throw new IllegalStateException();
}
@Override
void describeAsLowerBound(StringBuilder sb) {
throw new AssertionError();
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append("+\u221e)");
}
@Override
Comparable<?> leastValueAbove(DiscreteDomain<Comparable<?>> domain) {
throw new AssertionError();
}
@Override
Comparable<?> greatestValueBelow(DiscreteDomain<Comparable<?>> domain) {
return domain.maxValue();
}
@Override
public int compareTo(Cut<Comparable<?>> o) {
return (o == this) ? 0 : 1;
}
@Override
public String toString() {
return "+\u221e";
}
private Object readResolve() {
return INSTANCE;
}
private static final long serialVersionUID = 0;
}
static <C extends Comparable> Cut<C> belowValue(C endpoint) {
return new BelowValue<C>(endpoint);
}
private static final class BelowValue<C extends Comparable> extends Cut<C> {
BelowValue(C endpoint) {
super(checkNotNull(endpoint));
}
@Override
boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) <= 0;
}
@Override
BoundType typeAsLowerBound() {
return BoundType.CLOSED;
}
@Override
BoundType typeAsUpperBound() {
return BoundType.OPEN;
}
@Override
Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
return this;
case OPEN:
@Nullable
C previous = domain.previous(endpoint);
return (previous == null) ? Cut.<C>belowAll() : new AboveValue<C>(previous);
default:
throw new AssertionError();
}
}
@Override
Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case CLOSED:
@Nullable
C previous = domain.previous(endpoint);
return (previous == null) ? Cut.<C>aboveAll() : new AboveValue<C>(previous);
case OPEN:
return this;
default:
throw new AssertionError();
}
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append('[').append(endpoint);
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(')');
}
@Override
C leastValueAbove(DiscreteDomain<C> domain) {
return endpoint;
}
@Override
C greatestValueBelow(DiscreteDomain<C> domain) {
return domain.previous(endpoint);
}
@Override
public int hashCode() {
return endpoint.hashCode();
}
@Override
public String toString() {
return "\\" + endpoint + "/";
}
private static final long serialVersionUID = 0;
}
static <C extends Comparable> Cut<C> aboveValue(C endpoint) {
return new AboveValue<C>(endpoint);
}
private static final class AboveValue<C extends Comparable> extends Cut<C> {
AboveValue(C endpoint) {
super(checkNotNull(endpoint));
}
@Override
boolean isLessThan(C value) {
return Range.compareOrThrow(endpoint, value) < 0;
}
@Override
BoundType typeAsLowerBound() {
return BoundType.OPEN;
}
@Override
BoundType typeAsUpperBound() {
return BoundType.CLOSED;
}
@Override
Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
return this;
case CLOSED:
@Nullable
C next = domain.next(endpoint);
return (next == null) ? Cut.<C>belowAll() : belowValue(next);
default:
throw new AssertionError();
}
}
@Override
Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
switch (boundType) {
case OPEN:
@Nullable
C next = domain.next(endpoint);
return (next == null) ? Cut.<C>aboveAll() : belowValue(next);
case CLOSED:
return this;
default:
throw new AssertionError();
}
}
@Override
void describeAsLowerBound(StringBuilder sb) {
sb.append('(').append(endpoint);
}
@Override
void describeAsUpperBound(StringBuilder sb) {
sb.append(endpoint).append(']');
}
@Override
C leastValueAbove(DiscreteDomain<C> domain) {
return domain.next(endpoint);
}
@Override
C greatestValueBelow(DiscreteDomain<C> domain) {
return endpoint;
}
@Override
Cut<C> canonical(DiscreteDomain<C> domain) {
C next = leastValueAbove(domain);
return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
}
@Override
public int hashCode() {
return ~endpoint.hashCode();
}
@Override
public String toString() {
return "/" + endpoint + "\\";
}
private static final long serialVersionUID = 0;
}
}

View File

@ -0,0 +1,278 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.google.common.annotations.GwtCompatible;
/**
* A {@code RegularImmutableTable} optimized for dense data.
*/
@GwtCompatible
@Immutable
final class DenseImmutableTable<R, C, V> extends RegularImmutableTable<R, C, V> {
private final ImmutableMap<R, Integer> rowKeyToIndex;
private final ImmutableMap<C, Integer> columnKeyToIndex;
private final ImmutableMap<R, Map<C, V>> rowMap;
private final ImmutableMap<C, Map<R, V>> columnMap;
private final int[] rowCounts;
private final int[] columnCounts;
private final V[][] values;
private final int[] iterationOrderRow;
private final int[] iterationOrderColumn;
private static <E> ImmutableMap<E, Integer> makeIndex(ImmutableSet<E> set) {
ImmutableMap.Builder<E, Integer> indexBuilder = ImmutableMap.builder();
int i = 0;
for (E key : set) {
indexBuilder.put(key, i);
i++;
}
return indexBuilder.build();
}
DenseImmutableTable(ImmutableList<Cell<R, C, V>> cellList, ImmutableSet<R> rowSpace, ImmutableSet<C> columnSpace) {
@SuppressWarnings("unchecked")
V[][] array = (V[][]) new Object[rowSpace.size()][columnSpace.size()];
this.values = array;
this.rowKeyToIndex = makeIndex(rowSpace);
this.columnKeyToIndex = makeIndex(columnSpace);
rowCounts = new int[rowKeyToIndex.size()];
columnCounts = new int[columnKeyToIndex.size()];
int[] iterationOrderRow = new int[cellList.size()];
int[] iterationOrderColumn = new int[cellList.size()];
for (int i = 0; i < cellList.size(); i++) {
Cell<R, C, V> cell = cellList.get(i);
R rowKey = cell.getRowKey();
C columnKey = cell.getColumnKey();
int rowIndex = rowKeyToIndex.get(rowKey);
int columnIndex = columnKeyToIndex.get(columnKey);
V existingValue = values[rowIndex][columnIndex];
checkArgument(existingValue == null, "duplicate key: (%s, %s)", rowKey, columnKey);
values[rowIndex][columnIndex] = cell.getValue();
rowCounts[rowIndex]++;
columnCounts[columnIndex]++;
iterationOrderRow[i] = rowIndex;
iterationOrderColumn[i] = columnIndex;
}
this.iterationOrderRow = iterationOrderRow;
this.iterationOrderColumn = iterationOrderColumn;
this.rowMap = new RowMap();
this.columnMap = new ColumnMap();
}
/**
* An immutable map implementation backed by an indexed nullable array.
*/
private abstract static class ImmutableArrayMap<K, V> extends ImmutableMap<K, V> {
private final int size;
ImmutableArrayMap(int size) {
this.size = size;
}
abstract ImmutableMap<K, Integer> keyToIndex();
// True if getValue never returns null.
private boolean isFull() {
return size == keyToIndex().size();
}
K getKey(int index) {
return keyToIndex().keySet().asList().get(index);
}
@Nullable
abstract V getValue(int keyIndex);
@Override
ImmutableSet<K> createKeySet() {
return isFull() ? keyToIndex().keySet() : super.createKeySet();
}
@Override
public int size() {
return size;
}
@Override
public V get(@Nullable Object key) {
Integer keyIndex = keyToIndex().get(key);
return (keyIndex == null) ? null : getValue(keyIndex);
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
return new ImmutableMapEntrySet<K, V>() {
@Override
ImmutableMap<K, V> map() {
return ImmutableArrayMap.this;
}
@Override
public UnmodifiableIterator<Entry<K, V>> iterator() {
return new AbstractIterator<Entry<K, V>>() {
private int index = -1;
private final int maxIndex = keyToIndex().size();
@Override
protected Entry<K, V> computeNext() {
for (index++; index < maxIndex; index++) {
V value = getValue(index);
if (value != null) {
return Maps.immutableEntry(getKey(index), value);
}
}
return endOfData();
}
};
}
};
}
}
private final class Row extends ImmutableArrayMap<C, V> {
private final int rowIndex;
Row(int rowIndex) {
super(rowCounts[rowIndex]);
this.rowIndex = rowIndex;
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[rowIndex][keyIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class Column extends ImmutableArrayMap<R, V> {
private final int columnIndex;
Column(int columnIndex) {
super(columnCounts[columnIndex]);
this.columnIndex = columnIndex;
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
V getValue(int keyIndex) {
return values[keyIndex][columnIndex];
}
@Override
boolean isPartialView() {
return true;
}
}
private final class RowMap extends ImmutableArrayMap<R, Map<C, V>> {
private RowMap() {
super(rowCounts.length);
}
@Override
ImmutableMap<R, Integer> keyToIndex() {
return rowKeyToIndex;
}
@Override
Map<C, V> getValue(int keyIndex) {
return new Row(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
private final class ColumnMap extends ImmutableArrayMap<C, Map<R, V>> {
private ColumnMap() {
super(columnCounts.length);
}
@Override
ImmutableMap<C, Integer> keyToIndex() {
return columnKeyToIndex;
}
@Override
Map<R, V> getValue(int keyIndex) {
return new Column(keyIndex);
}
@Override
boolean isPartialView() {
return false;
}
}
@Override
public ImmutableMap<C, Map<R, V>> columnMap() {
return columnMap;
}
@Override
public ImmutableMap<R, Map<C, V>> rowMap() {
return rowMap;
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
Integer rowIndex = rowKeyToIndex.get(rowKey);
Integer columnIndex = columnKeyToIndex.get(columnKey);
return ((rowIndex == null) || (columnIndex == null)) ? null : values[rowIndex][columnIndex];
}
@Override
public int size() {
return iterationOrderRow.length;
}
@Override
Cell<R, C, V> getCell(int index) {
int rowIndex = iterationOrderRow[index];
int columnIndex = iterationOrderColumn[index];
R rowKey = rowKeySet().asList().get(rowIndex);
C columnKey = columnKeySet().asList().get(columnIndex);
V value = values[rowIndex][columnIndex];
return cellOf(rowKey, columnKey, value);
}
@Override
V getValue(int index) {
return values[iterationOrderRow[index]][iterationOrderColumn[index]];
}
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
/**
* A descending wrapper around an {@code ImmutableSortedMultiset}
*
* @author Louis Wasserman
*/
@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class DescendingImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
private final transient ImmutableSortedMultiset<E> forward;
DescendingImmutableSortedMultiset(ImmutableSortedMultiset<E> forward) {
this.forward = forward;
}
@Override
public int count(@Nullable Object element) {
return forward.count(element);
}
@Override
public Entry<E> firstEntry() {
return forward.lastEntry();
}
@Override
public Entry<E> lastEntry() {
return forward.firstEntry();
}
@Override
public int size() {
return forward.size();
}
@Override
public ImmutableSortedSet<E> elementSet() {
return forward.elementSet().descendingSet();
}
@Override
Entry<E> getEntry(int index) {
return forward.entrySet().asList().reverse().get(index);
}
@Override
public ImmutableSortedMultiset<E> descendingMultiset() {
return forward;
}
@Override
public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
return forward.tailMultiset(upperBound, boundType).descendingMultiset();
}
@Override
public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
return forward.headMultiset(lowerBound, boundType).descendingMultiset();
}
@Override
boolean isPartialView() {
return forward.isPartialView();
}
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtIncompatible;
/**
* Skeletal implementation of {@link ImmutableSortedSet#descendingSet()}.
*
* @author Louis Wasserman
*/
class DescendingImmutableSortedSet<E> extends ImmutableSortedSet<E> {
private final ImmutableSortedSet<E> forward;
DescendingImmutableSortedSet(ImmutableSortedSet<E> forward) {
super(Ordering.from(forward.comparator()).reverse());
this.forward = forward;
}
@Override
public int size() {
return forward.size();
}
@Override
public UnmodifiableIterator<E> iterator() {
return forward.descendingIterator();
}
@Override
ImmutableSortedSet<E> headSetImpl(E toElement, boolean inclusive) {
return forward.tailSet(toElement, inclusive).descendingSet();
}
@Override
ImmutableSortedSet<E> subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return forward.subSet(toElement, toInclusive, fromElement, fromInclusive).descendingSet();
}
@Override
ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive) {
return forward.headSet(fromElement, inclusive).descendingSet();
}
@Override
@GwtIncompatible("NavigableSet")
public ImmutableSortedSet<E> descendingSet() {
return forward;
}
@Override
@GwtIncompatible("NavigableSet")
public UnmodifiableIterator<E> descendingIterator() {
return forward.iterator();
}
@Override
@GwtIncompatible("NavigableSet")
ImmutableSortedSet<E> createDescendingSet() {
throw new AssertionError("should never be called");
}
@Override
public E lower(E element) {
return forward.higher(element);
}
@Override
public E floor(E element) {
return forward.ceiling(element);
}
@Override
public E ceiling(E element) {
return forward.floor(element);
}
@Override
public E higher(E element) {
return forward.lower(element);
}
@Override
int indexOf(@Nullable Object target) {
int index = forward.indexOf(target);
if (index == -1) {
return index;
} else {
return size() - 1 - index;
}
}
@Override
boolean isPartialView() {
return forward.isPartialView();
}
}

View File

@ -0,0 +1,151 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Set;
import com.google.common.annotations.GwtCompatible;
/**
* A skeleton implementation of a descending multiset. Only needs
* {@code forwardMultiset()} and {@code entryIterator()}.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
abstract class DescendingMultiset<E> extends ForwardingMultiset<E> implements SortedMultiset<E> {
abstract SortedMultiset<E> forwardMultiset();
private transient Comparator<? super E> comparator;
@Override
public Comparator<? super E> comparator() {
Comparator<? super E> result = comparator;
if (result == null) {
return comparator = Ordering.from(forwardMultiset().comparator()).<E>reverse();
}
return result;
}
private transient NavigableSet<E> elementSet;
@Override
public NavigableSet<E> elementSet() {
NavigableSet<E> result = elementSet;
if (result == null) {
return elementSet = new SortedMultisets.NavigableElementSet<E>(this);
}
return result;
}
@Override
public Entry<E> pollFirstEntry() {
return forwardMultiset().pollLastEntry();
}
@Override
public Entry<E> pollLastEntry() {
return forwardMultiset().pollFirstEntry();
}
@Override
public SortedMultiset<E> headMultiset(E toElement, BoundType boundType) {
return forwardMultiset().tailMultiset(toElement, boundType).descendingMultiset();
}
@Override
public SortedMultiset<E> subMultiset(E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) {
return forwardMultiset().subMultiset(toElement, toBoundType, fromElement, fromBoundType).descendingMultiset();
}
@Override
public SortedMultiset<E> tailMultiset(E fromElement, BoundType boundType) {
return forwardMultiset().headMultiset(fromElement, boundType).descendingMultiset();
}
@Override
protected Multiset<E> delegate() {
return forwardMultiset();
}
@Override
public SortedMultiset<E> descendingMultiset() {
return forwardMultiset();
}
@Override
public Entry<E> firstEntry() {
return forwardMultiset().lastEntry();
}
@Override
public Entry<E> lastEntry() {
return forwardMultiset().firstEntry();
}
abstract Iterator<Entry<E>> entryIterator();
private transient Set<Entry<E>> entrySet;
@Override
public Set<Entry<E>> entrySet() {
Set<Entry<E>> result = entrySet;
return (result == null) ? entrySet = createEntrySet() : result;
}
Set<Entry<E>> createEntrySet() {
return new Multisets.EntrySet<E>() {
@Override
Multiset<E> multiset() {
return DescendingMultiset.this;
}
@Override
public Iterator<Entry<E>> iterator() {
return entryIterator();
}
@Override
public int size() {
return forwardMultiset().entrySet().size();
}
};
}
@Override
public Iterator<E> iterator() {
return Multisets.iteratorImpl(this);
}
@Override
public Object[] toArray() {
return standardToArray();
}
@Override
public <T> T[] toArray(T[] array) {
return standardToArray(array);
}
@Override
public String toString() {
return entrySet().toString();
}
}

View File

@ -0,0 +1,275 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.NoSuchElementException;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A descriptor for a <i>discrete</i> {@code Comparable} domain such as all
* {@link Integer} instances. A discrete domain is one that supports the three
* basic operations: {@link #next}, {@link #previous} and {@link #distance},
* according to their specifications. The methods {@link #minValue} and
* {@link #maxValue} should also be overridden for bounded types.
*
* <p>
* A discrete domain always represents the <i>entire</i> set of values of its
* type; it cannot represent partial domains such as "prime integers" or
* "strings of length 5."
*
* <p>
* See the Guava User Guide section on <a href=
* "http://code.google.com/p/guava-libraries/wiki/RangesExplained#Discrete_Domains">
* {@code DiscreteDomain}</a>.
*
* @author Kevin Bourrillion
* @since 10.0
*/
@GwtCompatible
@Beta
public abstract class DiscreteDomain<C extends Comparable> {
/**
* Returns the discrete domain for values of type {@code Integer}.
*
* @since 14.0 (since 10.0 as {@code DiscreteDomains.integers()})
*/
public static DiscreteDomain<Integer> integers() {
return IntegerDomain.INSTANCE;
}
private static final class IntegerDomain extends DiscreteDomain<Integer> implements Serializable {
private static final IntegerDomain INSTANCE = new IntegerDomain();
@Override
public Integer next(Integer value) {
int i = value;
return (i == Integer.MAX_VALUE) ? null : i + 1;
}
@Override
public Integer previous(Integer value) {
int i = value;
return (i == Integer.MIN_VALUE) ? null : i - 1;
}
@Override
public long distance(Integer start, Integer end) {
return (long) end - start;
}
@Override
public Integer minValue() {
return Integer.MIN_VALUE;
}
@Override
public Integer maxValue() {
return Integer.MAX_VALUE;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.integers()";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the discrete domain for values of type {@code Long}.
*
* @since 14.0 (since 10.0 as {@code DiscreteDomains.longs()})
*/
public static DiscreteDomain<Long> longs() {
return LongDomain.INSTANCE;
}
private static final class LongDomain extends DiscreteDomain<Long> implements Serializable {
private static final LongDomain INSTANCE = new LongDomain();
@Override
public Long next(Long value) {
long l = value;
return (l == Long.MAX_VALUE) ? null : l + 1;
}
@Override
public Long previous(Long value) {
long l = value;
return (l == Long.MIN_VALUE) ? null : l - 1;
}
@Override
public long distance(Long start, Long end) {
long result = end - start;
if (end > start && result < 0) { // overflow
return Long.MAX_VALUE;
}
if (end < start && result > 0) { // underflow
return Long.MIN_VALUE;
}
return result;
}
@Override
public Long minValue() {
return Long.MIN_VALUE;
}
@Override
public Long maxValue() {
return Long.MAX_VALUE;
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.longs()";
}
private static final long serialVersionUID = 0;
}
/**
* Returns the discrete domain for values of type {@code BigInteger}.
*
* @since 15.0
*/
public static DiscreteDomain<BigInteger> bigIntegers() {
return BigIntegerDomain.INSTANCE;
}
private static final class BigIntegerDomain extends DiscreteDomain<BigInteger> implements Serializable {
private static final BigIntegerDomain INSTANCE = new BigIntegerDomain();
private static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
@Override
public BigInteger next(BigInteger value) {
return value.add(BigInteger.ONE);
}
@Override
public BigInteger previous(BigInteger value) {
return value.subtract(BigInteger.ONE);
}
@Override
public long distance(BigInteger start, BigInteger end) {
return end.subtract(start).max(MIN_LONG).min(MAX_LONG).longValue();
}
private Object readResolve() {
return INSTANCE;
}
@Override
public String toString() {
return "DiscreteDomain.bigIntegers()";
}
private static final long serialVersionUID = 0;
}
/** Constructor for use by subclasses. */
protected DiscreteDomain() {
}
/**
* Returns the unique least value of type {@code C} that is greater than
* {@code value}, or {@code null} if none exists. Inverse operation to
* {@link #previous}.
*
* @param value any value of type {@code C}
* @return the least value greater than {@code value}, or {@code null} if
* {@code value} is {@code maxValue()}
*/
public abstract C next(C value);
/**
* Returns the unique greatest value of type {@code C} that is less than
* {@code value}, or {@code null} if none exists. Inverse operation to
* {@link #next}.
*
* @param value any value of type {@code C}
* @return the greatest value less than {@code value}, or {@code null} if
* {@code value} is {@code minValue()}
*/
public abstract C previous(C value);
/**
* Returns a signed value indicating how many nested invocations of
* {@link #next} (if positive) or {@link #previous} (if negative) are needed to
* reach {@code end} starting from {@code start}. For example, if {@code end =
* next(next(next(start)))}, then {@code distance(start, end) == 3} and {@code
* distance(end, start) == -3}. As well, {@code distance(a, a)} is always zero.
*
* <p>
* Note that this function is necessarily well-defined for any discrete type.
*
* @return the distance as described above, or {@link Long#MIN_VALUE} or
* {@link Long#MAX_VALUE} if the distance is too small or too large,
* respectively.
*/
public abstract long distance(C start, C end);
/**
* Returns the minimum value of type {@code C}, if it has one. The minimum value
* is the unique value for which {@link Comparable#compareTo(Object)} never
* returns a positive value for any input of type {@code C}.
*
* <p>
* The default implementation throws {@code NoSuchElementException}.
*
* @return the minimum value of type {@code C}; never null
* @throws NoSuchElementException if the type has no (practical) minimum value;
* for example, {@link java.math.BigInteger}
*/
public C minValue() {
throw new NoSuchElementException();
}
/**
* Returns the maximum value of type {@code C}, if it has one. The maximum value
* is the unique value for which {@link Comparable#compareTo(Object)} never
* returns a negative value for any input of type {@code C}.
*
* <p>
* The default implementation throws {@code NoSuchElementException}.
*
* @return the maximum value of type {@code C}; never null
* @throws NoSuchElementException if the type has no (practical) maximum value;
* for example, {@link java.math.BigInteger}
*/
public C maxValue() {
throw new NoSuchElementException();
}
}

View File

@ -0,0 +1,158 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* An empty contiguous set.
*
* @author Gregory Kick
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("unchecked") // allow ungenerified Comparable types
final class EmptyContiguousSet<C extends Comparable> extends ContiguousSet<C> {
EmptyContiguousSet(DiscreteDomain<C> domain) {
super(domain);
}
@Override
public C first() {
throw new NoSuchElementException();
}
@Override
public C last() {
throw new NoSuchElementException();
}
@Override
public int size() {
return 0;
}
@Override
public ContiguousSet<C> intersection(ContiguousSet<C> other) {
return this;
}
@Override
public Range<C> range() {
throw new NoSuchElementException();
}
@Override
public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
throw new NoSuchElementException();
}
@Override
ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
return this;
}
@Override
ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement, boolean toInclusive) {
return this;
}
@Override
ContiguousSet<C> tailSetImpl(C fromElement, boolean fromInclusive) {
return this;
}
@GwtIncompatible("not used by GWT emulation")
@Override
int indexOf(Object target) {
return -1;
}
@Override
public UnmodifiableIterator<C> iterator() {
return Iterators.emptyIterator();
}
@GwtIncompatible("NavigableSet")
@Override
public UnmodifiableIterator<C> descendingIterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ImmutableList<C> asList() {
return ImmutableList.of();
}
@Override
public String toString() {
return "[]";
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public int hashCode() {
return 0;
}
@GwtIncompatible("serialization")
private static final class SerializedForm<C extends Comparable> implements Serializable {
private final DiscreteDomain<C> domain;
private SerializedForm(DiscreteDomain<C> domain) {
this.domain = domain;
}
private Object readResolve() {
return new EmptyContiguousSet<C>(domain);
}
private static final long serialVersionUID = 0;
}
@GwtIncompatible("serialization")
@Override
Object writeReplace() {
return new SerializedForm<C>(domain);
}
@GwtIncompatible("NavigableSet")
ImmutableSortedSet<C> createDescendingSet() {
return new EmptyImmutableSortedSet<C>(Ordering.natural().reverse());
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* Bimap with no mappings.
*
* @author Jared Levy
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
final class EmptyImmutableBiMap extends ImmutableBiMap<Object, Object> {
static final EmptyImmutableBiMap INSTANCE = new EmptyImmutableBiMap();
private EmptyImmutableBiMap() {
}
@Override
public ImmutableBiMap<Object, Object> inverse() {
return this;
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public Object get(@Nullable Object key) {
return null;
}
@Override
public ImmutableSet<Entry<Object, Object>> entrySet() {
return ImmutableSet.of();
}
@Override
ImmutableSet<Entry<Object, Object>> createEntrySet() {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSetMultimap<Object, Object> asMultimap() {
return ImmutableSetMultimap.of();
}
@Override
public ImmutableSet<Object> keySet() {
return ImmutableSet.of();
}
@Override
boolean isPartialView() {
return false;
}
Object readResolve() {
return INSTANCE; // preserve singleton property
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of {@link ImmutableListMultimap} with no entries.
*
* @author Jared Levy
*/
@GwtCompatible(serializable = true)
class EmptyImmutableListMultimap extends ImmutableListMultimap<Object, Object> {
static final EmptyImmutableListMultimap INSTANCE = new EmptyImmutableListMultimap();
private EmptyImmutableListMultimap() {
super(ImmutableMap.<Object, ImmutableList<Object>>of(), 0);
}
private Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,107 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An empty immutable set.
*
* @author Kevin Bourrillion
*/
@GwtCompatible(serializable = true, emulated = true)
final class EmptyImmutableSet extends ImmutableSet<Object> {
static final EmptyImmutableSet INSTANCE = new EmptyImmutableSet();
private EmptyImmutableSet() {
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean contains(@Nullable Object target) {
return false;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public UnmodifiableIterator<Object> iterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public ImmutableList<Object> asList() {
return ImmutableList.of();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public final int hashCode() {
return 0;
}
@Override
boolean isHashCodeFast() {
return true;
}
@Override
public String toString() {
return "[]";
}
Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Implementation of {@link ImmutableListMultimap} with no entries.
*
* @author Mike Ward
*/
@GwtCompatible(serializable = true)
class EmptyImmutableSetMultimap extends ImmutableSetMultimap<Object, Object> {
static final EmptyImmutableSetMultimap INSTANCE = new EmptyImmutableSetMultimap();
private EmptyImmutableSetMultimap() {
super(ImmutableMap.<Object, ImmutableSet<Object>>of(), 0, null);
}
private Object readResolve() {
return INSTANCE; // preserve singleton property
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An empty immutable sorted map.
*
* @author Louis Wasserman
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class EmptyImmutableSortedMap<K, V> extends ImmutableSortedMap<K, V> {
private final transient ImmutableSortedSet<K> keySet;
EmptyImmutableSortedMap(Comparator<? super K> comparator) {
this.keySet = ImmutableSortedSet.emptySet(comparator);
}
EmptyImmutableSortedMap(Comparator<? super K> comparator, ImmutableSortedMap<K, V> descendingMap) {
super(descendingMap);
this.keySet = ImmutableSortedSet.emptySet(comparator);
}
@Override
public V get(@Nullable Object key) {
return null;
}
@Override
public ImmutableSortedSet<K> keySet() {
return keySet;
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public ImmutableCollection<V> values() {
return ImmutableList.of();
}
@Override
public String toString() {
return "{}";
}
@Override
boolean isPartialView() {
return false;
}
@Override
public ImmutableSet<Entry<K, V>> entrySet() {
return ImmutableSet.of();
}
@Override
ImmutableSet<Entry<K, V>> createEntrySet() {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSetMultimap<K, V> asMultimap() {
return ImmutableSetMultimap.of();
}
@Override
public ImmutableSortedMap<K, V> headMap(K toKey, boolean inclusive) {
checkNotNull(toKey);
return this;
}
@Override
public ImmutableSortedMap<K, V> tailMap(K fromKey, boolean inclusive) {
checkNotNull(fromKey);
return this;
}
@Override
ImmutableSortedMap<K, V> createDescendingMap() {
return new EmptyImmutableSortedMap<K, V>(Ordering.from(comparator()).reverse(), this);
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Comparator;
import javax.annotation.Nullable;
/**
* An empty immutable sorted multiset.
*
* @author Louis Wasserman
*/
@SuppressWarnings("serial") // Uses writeReplace, not default serialization
final class EmptyImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
private final ImmutableSortedSet<E> elementSet;
EmptyImmutableSortedMultiset(Comparator<? super E> comparator) {
this.elementSet = ImmutableSortedSet.emptySet(comparator);
}
@Override
public Entry<E> firstEntry() {
return null;
}
@Override
public Entry<E> lastEntry() {
return null;
}
@Override
public int count(@Nullable Object element) {
return 0;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public int size() {
return 0;
}
@Override
public ImmutableSortedSet<E> elementSet() {
return elementSet;
}
@Override
Entry<E> getEntry(int index) {
throw new AssertionError("should never be called");
}
@Override
public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
checkNotNull(upperBound);
checkNotNull(boundType);
return this;
}
@Override
public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
checkNotNull(lowerBound);
checkNotNull(boundType);
return this;
}
@Override
public UnmodifiableIterator<E> iterator() {
return Iterators.emptyIterator();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Multiset) {
Multiset<?> other = (Multiset<?>) object;
return other.isEmpty();
}
return false;
}
@Override
boolean isPartialView() {
return false;
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public ImmutableList<E> asList() {
return ImmutableList.of();
}
}

View File

@ -0,0 +1,140 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* An empty immutable sorted set.
*
* @author Jared Levy
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // uses writeReplace(), not default serialization
class EmptyImmutableSortedSet<E> extends ImmutableSortedSet<E> {
EmptyImmutableSortedSet(Comparator<? super E> comparator) {
super(comparator);
}
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return true;
}
@Override
public boolean contains(@Nullable Object target) {
return false;
}
@Override
public boolean containsAll(Collection<?> targets) {
return targets.isEmpty();
}
@Override
public UnmodifiableIterator<E> iterator() {
return Iterators.emptyIterator();
}
@GwtIncompatible("NavigableSet")
@Override
public UnmodifiableIterator<E> descendingIterator() {
return Iterators.emptyIterator();
}
@Override
boolean isPartialView() {
return false;
}
@Override
public ImmutableList<E> asList() {
return ImmutableList.of();
}
@Override
int copyIntoArray(Object[] dst, int offset) {
return offset;
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof Set) {
Set<?> that = (Set<?>) object;
return that.isEmpty();
}
return false;
}
@Override
public int hashCode() {
return 0;
}
@Override
public String toString() {
return "[]";
}
@Override
public E first() {
throw new NoSuchElementException();
}
@Override
public E last() {
throw new NoSuchElementException();
}
@Override
ImmutableSortedSet<E> headSetImpl(E toElement, boolean inclusive) {
return this;
}
@Override
ImmutableSortedSet<E> subSetImpl(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return this;
}
@Override
ImmutableSortedSet<E> tailSetImpl(E fromElement, boolean inclusive) {
return this;
}
@Override
int indexOf(@Nullable Object target) {
return -1;
}
@Override
ImmutableSortedSet<E> createDescendingSet() {
return new EmptyImmutableSortedSet<E>(Ordering.from(comparator).reverse());
}
}

View File

@ -0,0 +1,146 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.Map;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A {@code BiMap} backed by two {@code EnumMap} instances. Null keys and values
* are not permitted. An {@code EnumBiMap} and its inverse are both
* serializable.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumBiMap<K extends Enum<K>, V extends Enum<V>> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
private transient Class<V> valueType;
/**
* Returns a new, empty {@code EnumBiMap} using the specified key and value
* types.
*
* @param keyType the key type
* @param valueType the value type
*/
public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Class<K> keyType, Class<V> valueType) {
return new EnumBiMap<K, V>(keyType, valueType);
}
/**
* Returns a new bimap with the same mappings as the specified map. If the
* specified map is an {@code EnumBiMap}, the new bimap has the same types as
* the provided map. Otherwise, the specified map must contain at least one
* mapping, in order to determine the key and value types.
*
* @param map the map whose mappings are to be placed in this map
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} instance
* and contains no mappings
*/
public static <K extends Enum<K>, V extends Enum<V>> EnumBiMap<K, V> create(Map<K, V> map) {
EnumBiMap<K, V> bimap = create(inferKeyType(map), inferValueType(map));
bimap.putAll(map);
return bimap;
}
private EnumBiMap(Class<K> keyType, Class<V> valueType) {
super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)), WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
this.keyType = keyType;
this.valueType = valueType;
}
static <K extends Enum<K>> Class<K> inferKeyType(Map<K, ?> map) {
if (map instanceof EnumBiMap) {
return ((EnumBiMap<K, ?>) map).keyType();
}
if (map instanceof EnumHashBiMap) {
return ((EnumHashBiMap<K, ?>) map).keyType();
}
checkArgument(!map.isEmpty());
return map.keySet().iterator().next().getDeclaringClass();
}
private static <V extends Enum<V>> Class<V> inferValueType(Map<?, V> map) {
if (map instanceof EnumBiMap) {
return ((EnumBiMap<?, V>) map).valueType;
}
checkArgument(!map.isEmpty());
return map.values().iterator().next().getDeclaringClass();
}
/** Returns the associated key type. */
public Class<K> keyType() {
return keyType;
}
/** Returns the associated value type. */
public Class<V> valueType() {
return valueType;
}
@Override
K checkKey(K key) {
return checkNotNull(key);
}
@Override
V checkValue(V value) {
return checkNotNull(value);
}
/**
* @serialData the key class, value class, number of entries, first key, first
* value, second key, second value, and so on.
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(keyType);
stream.writeObject(valueType);
Serialization.writeMap(this, stream);
}
@SuppressWarnings("unchecked") // reading fields populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
valueType = (Class<V>) stream.readObject();
setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
WellBehavedMap.wrap(new EnumMap<V, K>(valueType)));
Serialization.populateMap(this, stream);
}
@GwtIncompatible("not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,128 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* A {@code BiMap} backed by an {@code EnumMap} instance for keys-to-values, and
* a {@code HashMap} instance for values-to-keys. Null keys are not permitted,
* but null values are. An {@code EnumHashBiMap} and its inverse are both
* serializable.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap}</a>.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumHashBiMap<K extends Enum<K>, V> extends AbstractBiMap<K, V> {
private transient Class<K> keyType;
/**
* Returns a new, empty {@code EnumHashBiMap} using the specified key type.
*
* @param keyType the key type
*/
public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Class<K> keyType) {
return new EnumHashBiMap<K, V>(keyType);
}
/**
* Constructs a new bimap with the same mappings as the specified map. If the
* specified map is an {@code EnumHashBiMap} or an {@link EnumBiMap}, the new
* bimap has the same key type as the input bimap. Otherwise, the specified map
* must contain at least one mapping, in order to determine the key type.
*
* @param map the map whose mappings are to be placed in this map
* @throws IllegalArgumentException if map is not an {@code EnumBiMap} or an
* {@code EnumHashBiMap} instance and contains
* no mappings
*/
public static <K extends Enum<K>, V> EnumHashBiMap<K, V> create(Map<K, ? extends V> map) {
EnumHashBiMap<K, V> bimap = create(EnumBiMap.inferKeyType(map));
bimap.putAll(map);
return bimap;
}
private EnumHashBiMap(Class<K> keyType) {
super(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
Maps.<V, K>newHashMapWithExpectedSize(keyType.getEnumConstants().length));
this.keyType = keyType;
}
// Overriding these 3 methods to show that values may be null (but not keys)
@Override
K checkKey(K key) {
return checkNotNull(key);
}
@Override
public V put(K key, @Nullable V value) {
return super.put(key, value);
}
@Override
public V forcePut(K key, @Nullable V value) {
return super.forcePut(key, value);
}
/** Returns the associated key type. */
public Class<K> keyType() {
return keyType;
}
/**
* @serialData the key class, number of entries, first key, first value, second
* key, second value, and so on.
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(keyType);
Serialization.writeMap(this, stream);
}
@SuppressWarnings("unchecked") // reading field populated by writeObject
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
keyType = (Class<K>) stream.readObject();
setDelegates(WellBehavedMap.wrap(new EnumMap<K, V>(keyType)),
new HashMap<V, K>(keyType.getEnumConstants().length * 3 / 2));
Serialization.populateMap(this, stream);
}
@GwtIncompatible("only needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.EnumMap;
import java.util.Iterator;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Multiset implementation backed by an {@link EnumMap}.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
* {@code Multiset}</a>.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class EnumMultiset<E extends Enum<E>> extends AbstractMapBasedMultiset<E> {
/** Creates an empty {@code EnumMultiset}. */
public static <E extends Enum<E>> EnumMultiset<E> create(Class<E> type) {
return new EnumMultiset<E>(type);
}
/**
* Creates a new {@code EnumMultiset} containing the specified elements.
*
* <p>
* This implementation is highly efficient when {@code elements} is itself a
* {@link Multiset}.
*
* @param elements the elements that the multiset should contain
* @throws IllegalArgumentException if {@code elements} is empty
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements) {
Iterator<E> iterator = elements.iterator();
checkArgument(iterator.hasNext(), "EnumMultiset constructor passed empty Iterable");
EnumMultiset<E> multiset = new EnumMultiset<E>(iterator.next().getDeclaringClass());
Iterables.addAll(multiset, elements);
return multiset;
}
/**
* Returns a new {@code EnumMultiset} instance containing the given elements.
* Unlike {@link EnumMultiset#create(Iterable)}, this method does not produce an
* exception on an empty iterable.
*
* @since 14.0
*/
public static <E extends Enum<E>> EnumMultiset<E> create(Iterable<E> elements, Class<E> type) {
EnumMultiset<E> result = create(type);
Iterables.addAll(result, elements);
return result;
}
private transient Class<E> type;
/** Creates an empty {@code EnumMultiset}. */
private EnumMultiset(Class<E> type) {
super(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
this.type = type;
}
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeObject(type);
Serialization.writeMultiset(this, stream);
}
/**
* @serialData the {@code Class<E>} for the enum type, the number of distinct
* elements, the first element, its count, the second element, its
* count, and so on
*/
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
@SuppressWarnings("unchecked") // reading data stored by writeObject
Class<E> localType = (Class<E>) stream.readObject();
type = localType;
setBackingMap(WellBehavedMap.wrap(new EnumMap<E, Count>(type)));
Serialization.populateMultiset(this, stream);
}
@GwtIncompatible("Not needed in emulated source")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,138 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Queue;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
/**
* A non-blocking queue which automatically evicts elements from the head of the
* queue when attempting to add new elements onto the queue and it is full.
*
* <p>
* An evicting queue must be configured with a maximum size. Each time an
* element is added to a full queue, the queue automatically removes its head
* element. This is different from conventional bounded queues, which either
* block or reject new elements when full.
*
* <p>
* This class is not thread-safe, and does not accept null elements.
*
* @author Kurt Alfred Kluever
* @since 15.0
*/
@Beta
@GwtIncompatible("java.util.ArrayDeque")
public final class EvictingQueue<E> extends ForwardingQueue<E> implements Serializable {
private final Queue<E> delegate;
@VisibleForTesting
final int maxSize;
private EvictingQueue(int maxSize) {
checkArgument(maxSize >= 0, "maxSize (%s) must >= 0", maxSize);
this.delegate = new ArrayDeque<E>(maxSize);
this.maxSize = maxSize;
}
/**
* Creates and returns a new evicting queue that will hold up to {@code maxSize}
* elements.
*
* <p>
* When {@code maxSize} is zero, elements will be evicted immediately after
* being added to the queue.
*/
public static <E> EvictingQueue<E> create(int maxSize) {
return new EvictingQueue<E>(maxSize);
}
/**
* Returns the number of additional elements that this queue can accept without
* evicting; zero if the queue is currently full.
*
* @since 16.0
*/
public int remainingCapacity() {
return maxSize - size();
}
@Override
protected Queue<E> delegate() {
return delegate;
}
/**
* Adds the given element to this queue. If the queue is currently full, the
* element at the head of the queue is evicted to make room.
*
* @return {@code true} always
*/
@Override
public boolean offer(E e) {
return add(e);
}
/**
* Adds the given element to this queue. If the queue is currently full, the
* element at the head of the queue is evicted to make room.
*
* @return {@code true} always
*/
@Override
public boolean add(E e) {
checkNotNull(e); // check before removing
if (maxSize == 0) {
return true;
}
if (size() == maxSize) {
delegate.remove();
}
delegate.add(e);
return true;
}
@Override
public boolean addAll(Collection<? extends E> collection) {
return standardAddAll(collection);
}
@Override
public boolean contains(Object object) {
return delegate().contains(checkNotNull(object));
}
@Override
public boolean remove(Object object) {
return delegate().remove(checkNotNull(object));
}
// TODO(user): Do we want to checkNotNull each element in containsAll,
// removeAll, and retainAll?
private static final long serialVersionUID = 0L;
}

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/** An ordering that compares objects according to a given order. */
@GwtCompatible(serializable = true)
final class ExplicitOrdering<T> extends Ordering<T> implements Serializable {
final ImmutableMap<T, Integer> rankMap;
ExplicitOrdering(List<T> valuesInOrder) {
this(buildRankMap(valuesInOrder));
}
ExplicitOrdering(ImmutableMap<T, Integer> rankMap) {
this.rankMap = rankMap;
}
@Override
public int compare(T left, T right) {
return rank(left) - rank(right); // safe because both are nonnegative
}
private int rank(T value) {
Integer rank = rankMap.get(value);
if (rank == null) {
throw new IncomparableValueException(value);
}
return rank;
}
private static <T> ImmutableMap<T, Integer> buildRankMap(List<T> valuesInOrder) {
ImmutableMap.Builder<T, Integer> builder = ImmutableMap.builder();
int rank = 0;
for (T value : valuesInOrder) {
builder.put(value, rank++);
}
return builder.build();
}
@Override
public boolean equals(@Nullable Object object) {
if (object instanceof ExplicitOrdering) {
ExplicitOrdering<?> that = (ExplicitOrdering<?>) object;
return this.rankMap.equals(that.rankMap);
}
return false;
}
@Override
public int hashCode() {
return rankMap.hashCode();
}
@Override
public String toString() {
return "Ordering.explicit(" + rankMap.keySet() + ")";
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,393 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.collect.Maps.ImprovedAbstractMap;
/**
* Implementation of {@link Multimaps#filterEntries(Multimap, Predicate)}.
*
* @author Jared Levy
* @author Louis Wasserman
*/
@GwtCompatible
class FilteredEntryMultimap<K, V> extends AbstractMultimap<K, V> implements FilteredMultimap<K, V> {
final Multimap<K, V> unfiltered;
final Predicate<? super Entry<K, V>> predicate;
FilteredEntryMultimap(Multimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
this.unfiltered = checkNotNull(unfiltered);
this.predicate = checkNotNull(predicate);
}
@Override
public Multimap<K, V> unfiltered() {
return unfiltered;
}
@Override
public Predicate<? super Entry<K, V>> entryPredicate() {
return predicate;
}
@Override
public int size() {
return entries().size();
}
private boolean satisfies(K key, V value) {
return predicate.apply(Maps.immutableEntry(key, value));
}
final class ValuePredicate implements Predicate<V> {
private final K key;
ValuePredicate(K key) {
this.key = key;
}
@Override
public boolean apply(@Nullable V value) {
return satisfies(key, value);
}
}
static <E> Collection<E> filterCollection(Collection<E> collection, Predicate<? super E> predicate) {
if (collection instanceof Set) {
return Sets.filter((Set<E>) collection, predicate);
} else {
return Collections2.filter(collection, predicate);
}
}
@Override
public boolean containsKey(@Nullable Object key) {
return asMap().get(key) != null;
}
@Override
public Collection<V> removeAll(@Nullable Object key) {
return Objects.firstNonNull(asMap().remove(key), unmodifiableEmptyCollection());
}
Collection<V> unmodifiableEmptyCollection() {
// These return false, rather than throwing a UOE, on remove calls.
return (unfiltered instanceof SetMultimap) ? Collections.<V>emptySet() : Collections.<V>emptyList();
}
@Override
public void clear() {
entries().clear();
}
@Override
public Collection<V> get(final K key) {
return filterCollection(unfiltered.get(key), new ValuePredicate(key));
}
@Override
Collection<Entry<K, V>> createEntries() {
return filterCollection(unfiltered.entries(), predicate);
}
@Override
Collection<V> createValues() {
return new FilteredMultimapValues<K, V>(this);
}
@Override
Iterator<Entry<K, V>> entryIterator() {
throw new AssertionError("should never be called");
}
@Override
Map<K, Collection<V>> createAsMap() {
return new AsMap();
}
@Override
public Set<K> keySet() {
return asMap().keySet();
}
boolean removeEntriesIf(Predicate<? super Entry<K, Collection<V>>> predicate) {
Iterator<Entry<K, Collection<V>>> entryIterator = unfiltered.asMap().entrySet().iterator();
boolean changed = false;
while (entryIterator.hasNext()) {
Entry<K, Collection<V>> entry = entryIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty() && predicate.apply(Maps.immutableEntry(key, collection))) {
if (collection.size() == entry.getValue().size()) {
entryIterator.remove();
} else {
collection.clear();
}
changed = true;
}
}
return changed;
}
class AsMap extends ImprovedAbstractMap<K, Collection<V>> {
@Override
public boolean containsKey(@Nullable Object key) {
return get(key) != null;
}
@Override
public void clear() {
FilteredEntryMultimap.this.clear();
}
@Override
public Collection<V> get(@Nullable Object key) {
Collection<V> result = unfiltered.asMap().get(key);
if (result == null) {
return null;
}
@SuppressWarnings("unchecked") // key is equal to a K, if not a K itself
K k = (K) key;
result = filterCollection(result, new ValuePredicate(k));
return result.isEmpty() ? null : result;
}
@Override
public Collection<V> remove(@Nullable Object key) {
Collection<V> collection = unfiltered.asMap().get(key);
if (collection == null) {
return null;
}
@SuppressWarnings("unchecked") // it's definitely equal to a K
K k = (K) key;
List<V> result = Lists.newArrayList();
Iterator<V> itr = collection.iterator();
while (itr.hasNext()) {
V v = itr.next();
if (satisfies(k, v)) {
itr.remove();
result.add(v);
}
}
if (result.isEmpty()) {
return null;
} else if (unfiltered instanceof SetMultimap) {
return Collections.unmodifiableSet(Sets.newLinkedHashSet(result));
} else {
return Collections.unmodifiableList(result);
}
}
@Override
Set<K> createKeySet() {
return new Maps.KeySet<K, Collection<V>>(this) {
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(Maps.<K>keyPredicateOnEntries(in(c)));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(Maps.<K>keyPredicateOnEntries(not(in(c))));
}
@Override
public boolean remove(@Nullable Object o) {
return AsMap.this.remove(o) != null;
}
};
}
@Override
Set<Entry<K, Collection<V>>> createEntrySet() {
return new Maps.EntrySet<K, Collection<V>>() {
@Override
Map<K, Collection<V>> map() {
return AsMap.this;
}
@Override
public Iterator<Entry<K, Collection<V>>> iterator() {
return new AbstractIterator<Entry<K, Collection<V>>>() {
final Iterator<Entry<K, Collection<V>>> backingIterator = unfiltered.asMap().entrySet()
.iterator();
@Override
protected Entry<K, Collection<V>> computeNext() {
while (backingIterator.hasNext()) {
Entry<K, Collection<V>> entry = backingIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty()) {
return Maps.immutableEntry(key, collection);
}
}
return endOfData();
}
};
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(in(c));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
}
@Override
public int size() {
return Iterators.size(iterator());
}
};
}
@Override
Collection<Collection<V>> createValues() {
return new Maps.Values<K, Collection<V>>(AsMap.this) {
@Override
public boolean remove(@Nullable Object o) {
if (o instanceof Collection) {
Collection<?> c = (Collection<?>) o;
Iterator<Entry<K, Collection<V>>> entryIterator = unfiltered.asMap().entrySet().iterator();
while (entryIterator.hasNext()) {
Entry<K, Collection<V>> entry = entryIterator.next();
K key = entry.getKey();
Collection<V> collection = filterCollection(entry.getValue(), new ValuePredicate(key));
if (!collection.isEmpty() && c.equals(collection)) {
if (collection.size() == entry.getValue().size()) {
entryIterator.remove();
} else {
collection.clear();
}
return true;
}
}
}
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(in(c)));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(Maps.<Collection<V>>valuePredicateOnEntries(not(in(c))));
}
};
}
}
@Override
Multiset<K> createKeys() {
return new Keys();
}
class Keys extends Multimaps.Keys<K, V> {
Keys() {
super(FilteredEntryMultimap.this);
}
@Override
public int remove(@Nullable Object key, int occurrences) {
checkNonnegative(occurrences, "occurrences");
if (occurrences == 0) {
return count(key);
}
Collection<V> collection = unfiltered.asMap().get(key);
if (collection == null) {
return 0;
}
@SuppressWarnings("unchecked") // key is equal to a K, if not a K itself
K k = (K) key;
int oldCount = 0;
Iterator<V> itr = collection.iterator();
while (itr.hasNext()) {
V v = itr.next();
if (satisfies(k, v)) {
oldCount++;
if (oldCount <= occurrences) {
itr.remove();
}
}
}
return oldCount;
}
@Override
public Set<Multiset.Entry<K>> entrySet() {
return new Multisets.EntrySet<K>() {
@Override
Multiset<K> multiset() {
return Keys.this;
}
@Override
public Iterator<Multiset.Entry<K>> iterator() {
return Keys.this.entryIterator();
}
@Override
public int size() {
return FilteredEntryMultimap.this.keySet().size();
}
private boolean removeEntriesIf(final Predicate<? super Multiset.Entry<K>> predicate) {
return FilteredEntryMultimap.this.removeEntriesIf(new Predicate<Map.Entry<K, Collection<V>>>() {
@Override
public boolean apply(Map.Entry<K, Collection<V>> entry) {
return predicate.apply(Multisets.immutableEntry(entry.getKey(), entry.getValue().size()));
}
});
}
@Override
public boolean removeAll(Collection<?> c) {
return removeEntriesIf(in(c));
}
@Override
public boolean retainAll(Collection<?> c) {
return removeEntriesIf(not(in(c)));
}
};
}
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
/**
* Implementation of {@link Multimaps#filterEntries(SetMultimap, Predicate)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class FilteredEntrySetMultimap<K, V> extends FilteredEntryMultimap<K, V> implements FilteredSetMultimap<K, V> {
FilteredEntrySetMultimap(SetMultimap<K, V> unfiltered, Predicate<? super Entry<K, V>> predicate) {
super(unfiltered, predicate);
}
@Override
public SetMultimap<K, V> unfiltered() {
return (SetMultimap<K, V>) unfiltered;
}
@Override
public Set<V> get(K key) {
return (Set<V>) super.get(key);
}
@Override
public Set<V> removeAll(Object key) {
return (Set<V>) super.removeAll(key);
}
@Override
public Set<V> replaceValues(K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
@Override
Set<Entry<K, V>> createEntries() {
return Sets.filter(unfiltered().entries(), entryPredicate());
}
@Override
public Set<Entry<K, V>> entries() {
return (Set<Entry<K, V>>) super.entries();
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
/**
* Implementation of {@link Multimaps#filterKeys(ListMultimap, Predicate)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class FilteredKeyListMultimap<K, V> extends FilteredKeyMultimap<K, V> implements ListMultimap<K, V> {
FilteredKeyListMultimap(ListMultimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
super(unfiltered, keyPredicate);
}
@Override
public ListMultimap<K, V> unfiltered() {
return (ListMultimap<K, V>) super.unfiltered();
}
@Override
public List<V> get(K key) {
return (List<V>) super.get(key);
}
@Override
public List<V> removeAll(@Nullable Object key) {
return (List<V>) super.removeAll(key);
}
@Override
public List<V> replaceValues(K key, Iterable<? extends V> values) {
return (List<V>) super.replaceValues(key, values);
}
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkPositionIndex;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
/**
* Implementation of {@link Multimaps#filterKeys(Multimap, Predicate)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
class FilteredKeyMultimap<K, V> extends AbstractMultimap<K, V> implements FilteredMultimap<K, V> {
final Multimap<K, V> unfiltered;
final Predicate<? super K> keyPredicate;
FilteredKeyMultimap(Multimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
this.unfiltered = checkNotNull(unfiltered);
this.keyPredicate = checkNotNull(keyPredicate);
}
@Override
public Multimap<K, V> unfiltered() {
return unfiltered;
}
@Override
public Predicate<? super Entry<K, V>> entryPredicate() {
return Maps.keyPredicateOnEntries(keyPredicate);
}
@Override
public int size() {
int size = 0;
for (Collection<V> collection : asMap().values()) {
size += collection.size();
}
return size;
}
@Override
public boolean containsKey(@Nullable Object key) {
if (unfiltered.containsKey(key)) {
@SuppressWarnings("unchecked") // k is equal to a K, if not one itself
K k = (K) key;
return keyPredicate.apply(k);
}
return false;
}
@Override
public Collection<V> removeAll(Object key) {
return containsKey(key) ? unfiltered.removeAll(key) : unmodifiableEmptyCollection();
}
Collection<V> unmodifiableEmptyCollection() {
if (unfiltered instanceof SetMultimap) {
return ImmutableSet.of();
} else {
return ImmutableList.of();
}
}
@Override
public void clear() {
keySet().clear();
}
@Override
Set<K> createKeySet() {
return Sets.filter(unfiltered.keySet(), keyPredicate);
}
@Override
public Collection<V> get(K key) {
if (keyPredicate.apply(key)) {
return unfiltered.get(key);
} else if (unfiltered instanceof SetMultimap) {
return new AddRejectingSet<K, V>(key);
} else {
return new AddRejectingList<K, V>(key);
}
}
static class AddRejectingSet<K, V> extends ForwardingSet<V> {
final K key;
AddRejectingSet(K key) {
this.key = key;
}
@Override
public boolean add(V element) {
throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
}
@Override
public boolean addAll(Collection<? extends V> collection) {
checkNotNull(collection);
throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
}
@Override
protected Set<V> delegate() {
return Collections.emptySet();
}
}
static class AddRejectingList<K, V> extends ForwardingList<V> {
final K key;
AddRejectingList(K key) {
this.key = key;
}
@Override
public boolean add(V v) {
add(0, v);
return true;
}
@Override
public boolean addAll(Collection<? extends V> collection) {
addAll(0, collection);
return true;
}
@Override
public void add(int index, V element) {
checkPositionIndex(index, 0);
throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
}
@Override
public boolean addAll(int index, Collection<? extends V> elements) {
checkNotNull(elements);
checkPositionIndex(index, 0);
throw new IllegalArgumentException("Key does not satisfy predicate: " + key);
}
@Override
protected List<V> delegate() {
return Collections.emptyList();
}
}
@Override
Iterator<Entry<K, V>> entryIterator() {
throw new AssertionError("should never be called");
}
@Override
Collection<Entry<K, V>> createEntries() {
return new Entries();
}
class Entries extends ForwardingCollection<Entry<K, V>> {
@Override
protected Collection<Entry<K, V>> delegate() {
return Collections2.filter(unfiltered.entries(), entryPredicate());
}
@Override
@SuppressWarnings("unchecked")
public boolean remove(@Nullable Object o) {
if (o instanceof Entry) {
Entry<?, ?> entry = (Entry<?, ?>) o;
if (unfiltered.containsKey(entry.getKey())
// if this holds, then we know entry.getKey() is a K
&& keyPredicate.apply((K) entry.getKey())) {
return unfiltered.remove(entry.getKey(), entry.getValue());
}
}
return false;
}
}
@Override
Collection<V> createValues() {
return new FilteredMultimapValues<K, V>(this);
}
@Override
Map<K, Collection<V>> createAsMap() {
return Maps.filterKeys(unfiltered.asMap(), keyPredicate);
}
@Override
Multiset<K> createKeys() {
return Multisets.filter(unfiltered.keys(), keyPredicate);
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
/**
* Implementation of {@link Multimaps#filterKeys(SetMultimap, Predicate)}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class FilteredKeySetMultimap<K, V> extends FilteredKeyMultimap<K, V> implements FilteredSetMultimap<K, V> {
FilteredKeySetMultimap(SetMultimap<K, V> unfiltered, Predicate<? super K> keyPredicate) {
super(unfiltered, keyPredicate);
}
@Override
public SetMultimap<K, V> unfiltered() {
return (SetMultimap<K, V>) unfiltered;
}
@Override
public Set<V> get(K key) {
return (Set<V>) super.get(key);
}
@Override
public Set<V> removeAll(Object key) {
return (Set<V>) super.removeAll(key);
}
@Override
public Set<V> replaceValues(K key, Iterable<? extends V> values) {
return (Set<V>) super.replaceValues(key, values);
}
@Override
public Set<Entry<K, V>> entries() {
return (Set<Entry<K, V>>) super.entries();
}
@Override
Set<Entry<K, V>> createEntries() {
return new EntrySet();
}
class EntrySet extends Entries implements Set<Entry<K, V>> {
@Override
public int hashCode() {
return Sets.hashCodeImpl(this);
}
@Override
public boolean equals(@Nullable Object o) {
return Sets.equalsImpl(this, o);
}
}
}

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map.Entry;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Predicate;
/**
* An interface for all filtered multimap types.
*
* @author Louis Wasserman
*/
@GwtCompatible
interface FilteredMultimap<K, V> extends Multimap<K, V> {
Multimap<K, V> unfiltered();
Predicate<? super Entry<K, V>> entryPredicate();
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2013 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
/**
* Implementation for {@link FilteredMultimap#values()}.
*
* @author Louis Wasserman
*/
@GwtCompatible
final class FilteredMultimapValues<K, V> extends AbstractCollection<V> {
private final FilteredMultimap<K, V> multimap;
FilteredMultimapValues(FilteredMultimap<K, V> multimap) {
this.multimap = checkNotNull(multimap);
}
@Override
public Iterator<V> iterator() {
return Maps.valueIterator(multimap.entries().iterator());
}
@Override
public boolean contains(@Nullable Object o) {
return multimap.containsValue(o);
}
@Override
public int size() {
return multimap.size();
}
@Override
public boolean remove(@Nullable Object o) {
Predicate<? super Entry<K, V>> entryPredicate = multimap.entryPredicate();
for (Iterator<Entry<K, V>> unfilteredItr = multimap.unfiltered().entries().iterator(); unfilteredItr
.hasNext();) {
Map.Entry<K, V> entry = unfilteredItr.next();
if (entryPredicate.apply(entry) && Objects.equal(entry.getValue(), o)) {
unfilteredItr.remove();
return true;
}
}
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return Iterables.removeIf(multimap.unfiltered().entries(),
// explicit <Entry<K, V>> is required to build with JDK6
Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
Maps.<V>valuePredicateOnEntries(Predicates.in(c))));
}
@Override
public boolean retainAll(Collection<?> c) {
return Iterables.removeIf(multimap.unfiltered().entries(),
// explicit <Entry<K, V>> is required to build with JDK6
Predicates.<Entry<K, V>>and(multimap.entryPredicate(),
Maps.<V>valuePredicateOnEntries(Predicates.not(Predicates.in(c)))));
}
@Override
public void clear() {
multimap.clear();
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* A supertype for filtered {@link SetMultimap} implementations.
*
* @author Louis Wasserman
*/
@GwtCompatible
interface FilteredSetMultimap<K, V> extends FilteredMultimap<K, V>, SetMultimap<K, V> {
@Override
SetMultimap<K, V> unfiltered();
}

View File

@ -0,0 +1,514 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
/**
* {@code FluentIterable} provides a rich interface for manipulating
* {@code Iterable} instances in a chained fashion. A {@code FluentIterable} can
* be created from an {@code Iterable}, or from a set of elements. The following
* types of methods are provided on {@code FluentIterable}:
* <ul>
* <li>chained methods which return a new {@code FluentIterable} based in some
* way on the contents of the current one (for example {@link #transform})
* <li>conversion methods which copy the {@code FluentIterable}'s contents into
* a new collection or array (for example {@link #toList})
* <li>element extraction methods which facilitate the retrieval of certain
* elements (for example {@link #last})
* <li>query methods which answer questions about the {@code FluentIterable}'s
* contents (for example {@link #anyMatch})
* </ul>
*
* <p>
* Here is an example that merges the lists returned by two separate database
* calls, transforms it by invoking {@code toString()} on each element, and
* returns the first 10 elements as an {@code ImmutableList}:
*
* <pre>
* {@code
*
* FluentIterable
* .from(database.getClientList())
* .filter(activeInLastMonth())
* .transform(Functions.toStringFunction())
* .limit(10)
* .toList();}
* </pre>
*
* <p>
* Anything which can be done using {@code FluentIterable} could be done in a
* different fashion (often with {@link Iterables}), however the use of
* {@code FluentIterable} makes many sets of operations significantly more
* concise.
*
* @author Marcin Mikosik
* @since 12.0
*/
@GwtCompatible(emulated = true)
public abstract class FluentIterable<E> implements Iterable<E> {
// We store 'iterable' and use it instead of 'this' to allow Iterables to
// perform instanceof
// checks on the _original_ iterable when FluentIterable.from is used.
private final Iterable<E> iterable;
/** Constructor for use by subclasses. */
protected FluentIterable() {
this.iterable = this;
}
FluentIterable(Iterable<E> iterable) {
this.iterable = checkNotNull(iterable);
}
/**
* Returns a fluent iterable that wraps {@code iterable}, or {@code iterable}
* itself if it is already a {@code FluentIterable}.
*/
public static <E> FluentIterable<E> from(final Iterable<E> iterable) {
return (iterable instanceof FluentIterable) ? (FluentIterable<E>) iterable : new FluentIterable<E>(iterable) {
@Override
public Iterator<E> iterator() {
return iterable.iterator();
}
};
}
/**
* Construct a fluent iterable from another fluent iterable. This is obviously
* never necessary, but is intended to help call out cases where one migration
* from {@code Iterable} to {@code FluentIterable} has obviated the need to
* explicitly convert to a {@code FluentIterable}.
*
* @deprecated instances of {@code FluentIterable} don't need to be converted to
* {@code FluentIterable}
*/
@Deprecated
public static <E> FluentIterable<E> from(FluentIterable<E> iterable) {
return checkNotNull(iterable);
}
/**
* Returns a string representation of this fluent iterable, with the format
* {@code [e1, e2, ..., en]}.
*/
@Override
public String toString() {
return Iterables.toString(iterable);
}
/**
* Returns the number of elements in this fluent iterable.
*/
public final int size() {
return Iterables.size(iterable);
}
/**
* Returns {@code true} if this fluent iterable contains any object for which
* {@code equals(element)} is true.
*/
public final boolean contains(@Nullable Object element) {
return Iterables.contains(iterable, element);
}
/**
* Returns a fluent iterable whose {@code Iterator} cycles indefinitely over the
* elements of this fluent iterable.
*
* <p>
* That iterator supports {@code remove()} if {@code iterable.iterator()} does.
* After {@code remove()} is called, subsequent cycles omit the removed element,
* which is no longer in this fluent iterable. The iterator's {@code hasNext()}
* method returns {@code true} until this fluent iterable is empty.
*
* <p>
* <b>Warning:</b> Typical uses of the resulting iterator may produce an
* infinite loop. You should use an explicit {@code break} or be certain that
* you will eventually remove all the elements.
*/
@CheckReturnValue
public final FluentIterable<E> cycle() {
return from(Iterables.cycle(iterable));
}
/**
* Returns the elements from this fluent iterable that satisfy a predicate. The
* resulting fluent iterable's iterator does not support {@code remove()}.
*/
@CheckReturnValue
public final FluentIterable<E> filter(Predicate<? super E> predicate) {
return from(Iterables.filter(iterable, predicate));
}
/**
* Returns the elements from this fluent iterable that are instances of class
* {@code type}.
*
* @param type the type of elements desired
*/
@GwtIncompatible("Class.isInstance")
@CheckReturnValue
public final <T> FluentIterable<T> filter(Class<T> type) {
return from(Iterables.filter(iterable, type));
}
/**
* Returns {@code true} if any element in this fluent iterable satisfies the
* predicate.
*/
public final boolean anyMatch(Predicate<? super E> predicate) {
return Iterables.any(iterable, predicate);
}
/**
* Returns {@code true} if every element in this fluent iterable satisfies the
* predicate. If this fluent iterable is empty, {@code true} is returned.
*/
public final boolean allMatch(Predicate<? super E> predicate) {
return Iterables.all(iterable, predicate);
}
/**
* Returns an {@link Optional} containing the first element in this fluent
* iterable that satisfies the given predicate, if such an element exists.
*
* <p>
* <b>Warning:</b> avoid using a {@code predicate} that matches {@code null}. If
* {@code null} is matched in this fluent iterable, a
* {@link NullPointerException} will be thrown.
*/
public final Optional<E> firstMatch(Predicate<? super E> predicate) {
return Iterables.tryFind(iterable, predicate);
}
/**
* Returns a fluent iterable that applies {@code function} to each element of
* this fluent iterable.
*
* <p>
* The returned fluent iterable's iterator supports {@code remove()} if this
* iterable's iterator does. After a successful {@code remove()} call, this
* fluent iterable no longer contains the corresponding element.
*/
public final <T> FluentIterable<T> transform(Function<? super E, T> function) {
return from(Iterables.transform(iterable, function));
}
/**
* Applies {@code function} to each element of this fluent iterable and returns
* a fluent iterable with the concatenated combination of results.
* {@code function} returns an Iterable of results.
*
* <p>
* The returned fluent iterable's iterator supports {@code remove()} if this
* function-returned iterables' iterator does. After a successful
* {@code remove()} call, the returned fluent iterable no longer contains the
* corresponding element.
*
* @since 13.0 (required {@code Function<E, Iterable<T>>} until 14.0)
*/
public <T> FluentIterable<T> transformAndConcat(Function<? super E, ? extends Iterable<? extends T>> function) {
return from(Iterables.concat(transform(function)));
}
/**
* Returns an {@link Optional} containing the first element in this fluent
* iterable. If the iterable is empty, {@code Optional.absent()} is returned.
*
* @throws NullPointerException if the first element is null; if this is a
* possibility, use {@code iterator().next()} or
* {@link Iterables#getFirst} instead.
*/
public final Optional<E> first() {
Iterator<E> iterator = iterable.iterator();
return iterator.hasNext() ? Optional.of(iterator.next()) : Optional.<E>absent();
}
/**
* Returns an {@link Optional} containing the last element in this fluent
* iterable. If the iterable is empty, {@code Optional.absent()} is returned.
*
* @throws NullPointerException if the last element is null; if this is a
* possibility, use {@link Iterables#getLast}
* instead.
*/
public final Optional<E> last() {
// Iterables#getLast was inlined here so we don't have to throw/catch a NSEE
// TODO(kevinb): Support a concurrently modified collection?
if (iterable instanceof List) {
List<E> list = (List<E>) iterable;
if (list.isEmpty()) {
return Optional.absent();
}
return Optional.of(list.get(list.size() - 1));
}
Iterator<E> iterator = iterable.iterator();
if (!iterator.hasNext()) {
return Optional.absent();
}
/*
* TODO(kevinb): consider whether this "optimization" is worthwhile. Users with
* SortedSets tend to know they are SortedSets and probably would not call this
* method.
*/
if (iterable instanceof SortedSet) {
SortedSet<E> sortedSet = (SortedSet<E>) iterable;
return Optional.of(sortedSet.last());
}
while (true) {
E current = iterator.next();
if (!iterator.hasNext()) {
return Optional.of(current);
}
}
}
/**
* Returns a view of this fluent iterable that skips its first
* {@code numberToSkip} elements. If this fluent iterable contains fewer than
* {@code numberToSkip} elements, the returned fluent iterable skips all of its
* elements.
*
* <p>
* Modifications to this fluent iterable before a call to {@code iterator()} are
* reflected in the returned fluent iterable. That is, the its iterator skips
* the first {@code numberToSkip} elements that exist when the iterator is
* created, not when {@code skip()} is called.
*
* <p>
* The returned fluent iterable's iterator supports {@code remove()} if the
* {@code Iterator} of this fluent iterable supports it. Note that it is
* <i>not</i> possible to delete the last skipped element by immediately calling
* {@code remove()} on the returned fluent iterable's iterator, as the
* {@code Iterator} contract states that a call to {@code * remove()} before a
* call to {@code next()} will throw an {@link IllegalStateException}.
*/
@CheckReturnValue
public final FluentIterable<E> skip(int numberToSkip) {
return from(Iterables.skip(iterable, numberToSkip));
}
/**
* Creates a fluent iterable with the first {@code size} elements of this fluent
* iterable. If this fluent iterable does not contain that many elements, the
* returned fluent iterable will have the same behavior as this fluent iterable.
* The returned fluent iterable's iterator supports {@code remove()} if this
* fluent iterable's iterator does.
*
* @param size the maximum number of elements in the returned fluent iterable
* @throws IllegalArgumentException if {@code size} is negative
*/
@CheckReturnValue
public final FluentIterable<E> limit(int size) {
return from(Iterables.limit(iterable, size));
}
/**
* Determines whether this fluent iterable is empty.
*/
public final boolean isEmpty() {
return !iterable.iterator().hasNext();
}
/**
* Returns an {@code ImmutableList} containing all of the elements from this
* fluent iterable in proper sequence.
*
* @since 14.0 (since 12.0 as {@code toImmutableList()}).
*/
public final ImmutableList<E> toList() {
return ImmutableList.copyOf(iterable);
}
/**
* Returns an {@code ImmutableList} containing all of the elements from this
* {@code
* FluentIterable} in the order specified by {@code comparator}. To produce an
* {@code
* ImmutableList} sorted by its natural ordering, use
* {@code toSortedList(Ordering.natural())}.
*
* @param comparator the function by which to sort list elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 13.0 as {@code toSortedImmutableList()}).
*/
@Beta
public final ImmutableList<E> toSortedList(Comparator<? super E> comparator) {
return Ordering.from(comparator).immutableSortedCopy(iterable);
}
/**
* Returns an {@code ImmutableSet} containing all of the elements from this
* fluent iterable with duplicates removed.
*
* @since 14.0 (since 12.0 as {@code toImmutableSet()}).
*/
public final ImmutableSet<E> toSet() {
return ImmutableSet.copyOf(iterable);
}
/**
* Returns an {@code ImmutableSortedSet} containing all of the elements from
* this {@code
* FluentIterable} in the order specified by {@code comparator}, with duplicates
* (determined by {@code comparator.compare(x, y) == 0}) removed. To produce an
* {@code ImmutableSortedSet} sorted by its natural ordering, use
* {@code toSortedSet(Ordering.natural())}.
*
* @param comparator the function by which to sort set elements
* @throws NullPointerException if any element is null
* @since 14.0 (since 12.0 as {@code toImmutableSortedSet()}).
*/
public final ImmutableSortedSet<E> toSortedSet(Comparator<? super E> comparator) {
return ImmutableSortedSet.copyOf(comparator, iterable);
}
/**
* Returns an immutable map for which the elements of this
* {@code FluentIterable} are the keys in the same order, mapped to values by
* the given function. If this iterable contains duplicate elements, the
* returned map will contain each distinct element once in the order it first
* appears.
*
* @throws NullPointerException if any element of this iterable is {@code null},
* or if {@code
* valueFunction} produces {@code null} for any key
* @since 14.0
*/
public final <V> ImmutableMap<E, V> toMap(Function<? super E, V> valueFunction) {
return Maps.toMap(iterable, valueFunction);
}
/**
* Creates an index {@code ImmutableListMultimap} that contains the results of
* applying a specified function to each item in this {@code FluentIterable} of
* values. Each element of this iterable will be stored as a value in the
* resulting multimap, yielding a multimap with the same size as this iterable.
* The key used to store that value in the multimap will be the result of
* calling the function on that value. The resulting multimap is created as an
* immutable snapshot. In the returned multimap, keys appear in the order they
* are first encountered, and the values corresponding to each key appear in the
* same order as they are encountered.
*
* @param keyFunction the function used to produce the key for each value
* @throws NullPointerException if any of the following cases is true:
* <ul>
* <li>{@code keyFunction} is null
* <li>An element in this fluent iterable is null
* <li>{@code keyFunction} returns {@code null} for
* any element of this iterable
* </ul>
* @since 14.0
*/
public final <K> ImmutableListMultimap<K, E> index(Function<? super E, K> keyFunction) {
return Multimaps.index(iterable, keyFunction);
}
/**
* Returns an immutable map for which the {@link java.util.Map#values} are the
* elements of this {@code FluentIterable} in the given order, and each key is
* the product of invoking a supplied function on its corresponding value.
*
* @param keyFunction the function used to produce the key for each value
* @throws IllegalArgumentException if {@code keyFunction} produces the same key
* for more than one value in this fluent
* iterable
* @throws NullPointerException if any element of this fluent iterable is
* null, or if {@code keyFunction} produces
* {@code null} for any value
* @since 14.0
*/
public final <K> ImmutableMap<K, E> uniqueIndex(Function<? super E, K> keyFunction) {
return Maps.uniqueIndex(iterable, keyFunction);
}
/**
* Returns an array containing all of the elements from this fluent iterable in
* iteration order.
*
* @param type the type of the elements
* @return a newly-allocated array into which all the elements of this fluent
* iterable have been copied
*/
@GwtIncompatible("Array.newArray(Class, int)")
public final E[] toArray(Class<E> type) {
return Iterables.toArray(iterable, type);
}
/**
* Copies all the elements from this fluent iterable to {@code collection}. This
* is equivalent to calling {@code Iterables.addAll(collection, this)}.
*
* @param collection the collection to copy elements to
* @return {@code collection}, for convenience
* @since 14.0
*/
public final <C extends Collection<? super E>> C copyInto(C collection) {
checkNotNull(collection);
if (iterable instanceof Collection) {
collection.addAll(Collections2.cast(iterable));
} else {
for (E item : iterable) {
collection.add(item);
}
}
return collection;
}
/**
* Returns the element at the specified position in this fluent iterable.
*
* @param position position of the element to return
* @return the element at the specified position in this fluent iterable
* @throws IndexOutOfBoundsException if {@code position} is negative or greater
* than or equal to the size of this fluent
* iterable
*/
public final E get(int position) {
return Iterables.get(iterable, position);
}
/**
* Function that transforms {@code Iterable<E>} into a fluent iterable.
*/
private static class FromIterableFunction<E> implements Function<Iterable<E>, FluentIterable<E>> {
@Override
public FluentIterable<E> apply(Iterable<E> fromObject) {
return FluentIterable.from(fromObject);
}
}
}

View File

@ -0,0 +1,257 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Iterator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* A collection which forwards all its method calls to another collection.
* Subclasses should override one or more methods to modify the behavior of the
* backing collection as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingCollection} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of
* {@link #addAll}, which can lead to unexpected behavior. In this case, you
* should override {@code addAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardAddAll} method.
*
* <p>
* The {@code standard} methods are not guaranteed to be thread-safe, even when
* all of the methods that they depend on are thread-safe.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingCollection<E> extends ForwardingObject implements Collection<E> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingCollection() {
}
@Override
protected abstract Collection<E> delegate();
@Override
public Iterator<E> iterator() {
return delegate().iterator();
}
@Override
public int size() {
return delegate().size();
}
@Override
public boolean removeAll(Collection<?> collection) {
return delegate().removeAll(collection);
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public boolean contains(Object object) {
return delegate().contains(object);
}
@Override
public boolean add(E element) {
return delegate().add(element);
}
@Override
public boolean remove(Object object) {
return delegate().remove(object);
}
@Override
public boolean containsAll(Collection<?> collection) {
return delegate().containsAll(collection);
}
@Override
public boolean addAll(Collection<? extends E> collection) {
return delegate().addAll(collection);
}
@Override
public boolean retainAll(Collection<?> collection) {
return delegate().retainAll(collection);
}
@Override
public void clear() {
delegate().clear();
}
@Override
public Object[] toArray() {
return delegate().toArray();
}
@Override
public <T> T[] toArray(T[] array) {
return delegate().toArray(array);
}
/**
* A sensible definition of {@link #contains} in terms of {@link #iterator}. If
* you override {@link #iterator}, you may wish to override {@link #contains} to
* forward to this implementation.
*
* @since 7.0
*/
protected boolean standardContains(@Nullable Object object) {
return Iterators.contains(iterator(), object);
}
/**
* A sensible definition of {@link #containsAll} in terms of {@link #contains} .
* If you override {@link #contains}, you may wish to override
* {@link #containsAll} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardContainsAll(Collection<?> collection) {
return Collections2.containsAllImpl(this, collection);
}
/**
* A sensible definition of {@link #addAll} in terms of {@link #add}. If you
* override {@link #add}, you may wish to override {@link #addAll} to forward to
* this implementation.
*
* @since 7.0
*/
protected boolean standardAddAll(Collection<? extends E> collection) {
return Iterators.addAll(this, collection.iterator());
}
/**
* A sensible definition of {@link #remove} in terms of {@link #iterator}, using
* the iterator's {@code remove} method. If you override {@link #iterator}, you
* may wish to override {@link #remove} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardRemove(@Nullable Object object) {
Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
if (Objects.equal(iterator.next(), object)) {
iterator.remove();
return true;
}
}
return false;
}
/**
* A sensible definition of {@link #removeAll} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override
* {@link #iterator}, you may wish to override {@link #removeAll} to forward to
* this implementation.
*
* @since 7.0
*/
protected boolean standardRemoveAll(Collection<?> collection) {
return Iterators.removeAll(iterator(), collection);
}
/**
* A sensible definition of {@link #retainAll} in terms of {@link #iterator},
* using the iterator's {@code remove} method. If you override
* {@link #iterator}, you may wish to override {@link #retainAll} to forward to
* this implementation.
*
* @since 7.0
*/
protected boolean standardRetainAll(Collection<?> collection) {
return Iterators.retainAll(iterator(), collection);
}
/**
* A sensible definition of {@link #clear} in terms of {@link #iterator}, using
* the iterator's {@code remove} method. If you override {@link #iterator}, you
* may wish to override {@link #clear} to forward to this implementation.
*
* @since 7.0
*/
protected void standardClear() {
Iterators.clear(iterator());
}
/**
* A sensible definition of {@link #isEmpty} as {@code !iterator().hasNext}. If
* you override {@link #isEmpty}, you may wish to override {@link #isEmpty} to
* forward to this implementation. Alternately, it may be more efficient to
* implement {@code isEmpty} as {@code size() == 0}.
*
* @since 7.0
*/
protected boolean standardIsEmpty() {
return !iterator().hasNext();
}
/**
* A sensible definition of {@link #toString} in terms of {@link #iterator}. If
* you override {@link #iterator}, you may wish to override {@link #toString} to
* forward to this implementation.
*
* @since 7.0
*/
protected String standardToString() {
return Collections2.toStringImpl(this);
}
/**
* A sensible definition of {@link #toArray()} in terms of
* {@link #toArray(Object[])}. If you override {@link #toArray(Object[])}, you
* may wish to override {@link #toArray} to forward to this implementation.
*
* @since 7.0
*/
protected Object[] standardToArray() {
Object[] newArray = new Object[size()];
return toArray(newArray);
}
/**
* A sensible definition of {@link #toArray(Object[])} in terms of {@link #size}
* and {@link #iterator}. If you override either of these methods, you may wish
* to override {@link #toArray} to forward to this implementation.
*
* @since 7.0
*/
protected <T> T[] standardToArray(T[] array) {
return ObjectArrays.toArrayImpl(this, array);
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Deque;
import java.util.Iterator;
/**
* A deque which forwards all its method calls to another deque. Subclasses
* should override one or more methods to modify the behavior of the backing
* deque as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingDeque} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of
* {@link #offer} which can lead to unexpected behavior. In this case, you
* should override {@code offer} as well.
*
* @author Kurt Alfred Kluever
* @since 12.0
*/
public abstract class ForwardingDeque<E> extends ForwardingQueue<E> implements Deque<E> {
/** Constructor for use by subclasses. */
protected ForwardingDeque() {
}
@Override
protected abstract Deque<E> delegate();
@Override
public void addFirst(E e) {
delegate().addFirst(e);
}
@Override
public void addLast(E e) {
delegate().addLast(e);
}
@Override
public Iterator<E> descendingIterator() {
return delegate().descendingIterator();
}
@Override
public E getFirst() {
return delegate().getFirst();
}
@Override
public E getLast() {
return delegate().getLast();
}
@Override
public boolean offerFirst(E e) {
return delegate().offerFirst(e);
}
@Override
public boolean offerLast(E e) {
return delegate().offerLast(e);
}
@Override
public E peekFirst() {
return delegate().peekFirst();
}
@Override
public E peekLast() {
return delegate().peekLast();
}
@Override
public E pollFirst() {
return delegate().pollFirst();
}
@Override
public E pollLast() {
return delegate().pollLast();
}
@Override
public E pop() {
return delegate().pop();
}
@Override
public void push(E e) {
delegate().push(e);
}
@Override
public E removeFirst() {
return delegate().removeFirst();
}
@Override
public E removeLast() {
return delegate().removeLast();
}
@Override
public boolean removeFirstOccurrence(Object o) {
return delegate().removeFirstOccurrence(o);
}
@Override
public boolean removeLastOccurrence(Object o) {
return delegate().removeLastOccurrence(o);
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Dummy class that makes the GWT serialization policy happy. It isn't used on
* the server-side.
*
* @author Hayward Chan
*/
@GwtCompatible(emulated = true)
class ForwardingImmutableCollection {
private ForwardingImmutableCollection() {
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Unused stub class, unreferenced under Java and manually emulated under GWT.
*
* @author Chris Povirk
*/
@GwtCompatible(emulated = true)
abstract class ForwardingImmutableList<E> {
private ForwardingImmutableList() {
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Unused stub class, unreferenced under Java and manually emulated under GWT.
*
* @author Chris Povirk
*/
@GwtCompatible(emulated = true)
abstract class ForwardingImmutableMap<K, V> {
private ForwardingImmutableMap() {
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import com.google.common.annotations.GwtCompatible;
/**
* Unused stub class, unreferenced under Java and manually emulated under GWT.
*
* @author Chris Povirk
*/
@GwtCompatible(emulated = true)
abstract class ForwardingImmutableSet<E> {
private ForwardingImmutableSet() {
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Iterator;
import com.google.common.annotations.GwtCompatible;
/**
* An iterator which forwards all its method calls to another iterator.
* Subclasses should override one or more methods to modify the behavior of the
* backing iterator as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingIterator<T> extends ForwardingObject implements Iterator<T> {
/** Constructor for use by subclasses. */
protected ForwardingIterator() {
}
@Override
protected abstract Iterator<T> delegate();
@Override
public boolean hasNext() {
return delegate().hasNext();
}
@Override
public T next() {
return delegate().next();
}
@Override
public void remove() {
delegate().remove();
}
}

View File

@ -0,0 +1,247 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A list which forwards all its method calls to another list. Subclasses should
* override one or more methods to modify the behavior of the backing list as
* desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* This class does not implement {@link net.lax1dude.eaglercraft.v1_8.RandomAccess}. If the delegate
* supports random access, the {@code ForwardingList} subclass should implement
* the {@code RandomAccess} interface.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingList} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of
* {@link #addAll}, which can lead to unexpected behavior. In this case, you
* should override {@code addAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardAddAll} method.
*
* <p>
* The {@code standard} methods and any collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingList<E> extends ForwardingCollection<E> implements List<E> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingList() {
}
@Override
protected abstract List<E> delegate();
@Override
public void add(int index, E element) {
delegate().add(index, element);
}
@Override
public boolean addAll(int index, Collection<? extends E> elements) {
return delegate().addAll(index, elements);
}
@Override
public E get(int index) {
return delegate().get(index);
}
@Override
public int indexOf(Object element) {
return delegate().indexOf(element);
}
@Override
public int lastIndexOf(Object element) {
return delegate().lastIndexOf(element);
}
@Override
public ListIterator<E> listIterator() {
return delegate().listIterator();
}
@Override
public ListIterator<E> listIterator(int index) {
return delegate().listIterator(index);
}
@Override
public E remove(int index) {
return delegate().remove(index);
}
@Override
public E set(int index, E element) {
return delegate().set(index, element);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return delegate().subList(fromIndex, toIndex);
}
@Override
public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible default implementation of {@link #add(Object)}, in terms of
* {@link #add(int, Object)}. If you override {@link #add(int, Object)}, you may
* wish to override {@link #add(Object)} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardAdd(E element) {
add(size(), element);
return true;
}
/**
* A sensible default implementation of {@link #addAll(int, Collection)}, in
* terms of the {@code add} method of {@link #listIterator(int)}. If you
* override {@link #listIterator(int)}, you may wish to override
* {@link #addAll(int, Collection)} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardAddAll(int index, Iterable<? extends E> elements) {
return Lists.addAllImpl(this, index, elements);
}
/**
* A sensible default implementation of {@link #indexOf}, in terms of
* {@link #listIterator()}. If you override {@link #listIterator()}, you may
* wish to override {@link #indexOf} to forward to this implementation.
*
* @since 7.0
*/
protected int standardIndexOf(@Nullable Object element) {
return Lists.indexOfImpl(this, element);
}
/**
* A sensible default implementation of {@link #lastIndexOf}, in terms of
* {@link #listIterator(int)}. If you override {@link #listIterator(int)}, you
* may wish to override {@link #lastIndexOf} to forward to this implementation.
*
* @since 7.0
*/
protected int standardLastIndexOf(@Nullable Object element) {
return Lists.lastIndexOfImpl(this, element);
}
/**
* A sensible default implementation of {@link #iterator}, in terms of
* {@link #listIterator()}. If you override {@link #listIterator()}, you may
* wish to override {@link #iterator} to forward to this implementation.
*
* @since 7.0
*/
protected Iterator<E> standardIterator() {
return listIterator();
}
/**
* A sensible default implementation of {@link #listIterator()}, in terms of
* {@link #listIterator(int)}. If you override {@link #listIterator(int)}, you
* may wish to override {@link #listIterator()} to forward to this
* implementation.
*
* @since 7.0
*/
protected ListIterator<E> standardListIterator() {
return listIterator(0);
}
/**
* A sensible default implementation of {@link #listIterator(int)}, in terms of
* {@link #size}, {@link #get(int)}, {@link #set(int, Object)},
* {@link #add(int, Object)}, and {@link #remove(int)}. If you override any of
* these methods, you may wish to override {@link #listIterator(int)} to forward
* to this implementation.
*
* @since 7.0
*/
@Beta
protected ListIterator<E> standardListIterator(int start) {
return Lists.listIteratorImpl(this, start);
}
/**
* A sensible default implementation of {@link #subList(int, int)}. If you
* override any other methods, you may wish to override
* {@link #subList(int, int)} to forward to this implementation.
*
* @since 7.0
*/
@Beta
protected List<E> standardSubList(int fromIndex, int toIndex) {
return Lists.subListImpl(this, fromIndex, toIndex);
}
/**
* A sensible definition of {@link #equals(Object)} in terms of {@link #size}
* and {@link #iterator}. If you override either of those methods, you may wish
* to override {@link #equals(Object)} to forward to this implementation.
*
* @since 7.0
*/
@Beta
protected boolean standardEquals(@Nullable Object object) {
return Lists.equalsImpl(this, object);
}
/**
* A sensible definition of {@link #hashCode} in terms of {@link #iterator}. If
* you override {@link #iterator}, you may wish to override {@link #hashCode} to
* forward to this implementation.
*
* @since 7.0
*/
@Beta
protected int standardHashCode() {
return Lists.hashCodeImpl(this);
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.ListIterator;
import com.google.common.annotations.GwtCompatible;
/**
* A list iterator which forwards all its method calls to another list iterator.
* Subclasses should override one or more methods to modify the behavior of the
* backing iterator as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingListIterator<E> extends ForwardingIterator<E> implements ListIterator<E> {
/** Constructor for use by subclasses. */
protected ForwardingListIterator() {
}
@Override
protected abstract ListIterator<E> delegate();
@Override
public void add(E element) {
delegate().add(element);
}
@Override
public boolean hasPrevious() {
return delegate().hasPrevious();
}
@Override
public int nextIndex() {
return delegate().nextIndex();
}
@Override
public E previous() {
return delegate().previous();
}
@Override
public int previousIndex() {
return delegate().previousIndex();
}
@Override
public void set(E element) {
delegate().set(element);
}
}

View File

@ -0,0 +1,59 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.List;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A list multimap which forwards all its method calls to another list multimap.
* Subclasses should override one or more methods to modify the behavior of the
* backing multimap as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Kurt Alfred Kluever
* @since 3.0
*/
@GwtCompatible
public abstract class ForwardingListMultimap<K, V> extends ForwardingMultimap<K, V> implements ListMultimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingListMultimap() {
}
@Override
protected abstract ListMultimap<K, V> delegate();
@Override
public List<V> get(@Nullable K key) {
return delegate().get(key);
}
@Override
public List<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
@Override
public List<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
}

View File

@ -0,0 +1,319 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* A map which forwards all its method calls to another map. Subclasses should
* override one or more methods to modify the behavior of the backing map as
* desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingMap} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #put} alone <i>will not</i> change the behavior of
* {@link #putAll}, which can lead to unexpected behavior. In this case, you
* should override {@code putAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardPutAll} method.
*
* <p>
* Each of the {@code standard} methods, where appropriate, use
* {@link Objects#equal} to test equality for both keys and values. This may not
* be the desired behavior for map implementations that use non-standard notions
* of key equality, such as a {@code SortedMap} whose comparator is not
* consistent with {@code equals}.
*
* <p>
* The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Kevin Bourrillion
* @author Jared Levy
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingMap<K, V> extends ForwardingObject implements Map<K, V> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMap() {
}
@Override
protected abstract Map<K, V> delegate();
@Override
public int size() {
return delegate().size();
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public V remove(Object object) {
return delegate().remove(object);
}
@Override
public void clear() {
delegate().clear();
}
@Override
public boolean containsKey(@Nullable Object key) {
return delegate().containsKey(key);
}
@Override
public boolean containsValue(@Nullable Object value) {
return delegate().containsValue(value);
}
@Override
public V get(@Nullable Object key) {
return delegate().get(key);
}
@Override
public V put(K key, V value) {
return delegate().put(key, value);
}
@Override
public void putAll(Map<? extends K, ? extends V> map) {
delegate().putAll(map);
}
@Override
public Set<K> keySet() {
return delegate().keySet();
}
@Override
public Collection<V> values() {
return delegate().values();
}
@Override
public Set<Entry<K, V>> entrySet() {
return delegate().entrySet();
}
@Override
public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #putAll(Map)} in terms of
* {@link #put(Object, Object)}. If you override {@link #put(Object, Object)},
* you may wish to override {@link #putAll(Map)} to forward to this
* implementation.
*
* @since 7.0
*/
protected void standardPutAll(Map<? extends K, ? extends V> map) {
Maps.putAllImpl(this, map);
}
/**
* A sensible, albeit inefficient, definition of {@link #remove} in terms of the
* {@code iterator} method of {@link #entrySet}. If you override
* {@link #entrySet}, you may wish to override {@link #remove} to forward to
* this implementation.
*
* <p>
* Alternately, you may wish to override {@link #remove} with {@code
* keySet().remove}, assuming that approach would not lead to an infinite loop.
*
* @since 7.0
*/
@Beta
protected V standardRemove(@Nullable Object key) {
Iterator<Entry<K, V>> entryIterator = entrySet().iterator();
while (entryIterator.hasNext()) {
Entry<K, V> entry = entryIterator.next();
if (Objects.equal(entry.getKey(), key)) {
V value = entry.getValue();
entryIterator.remove();
return value;
}
}
return null;
}
/**
* A sensible definition of {@link #clear} in terms of the {@code iterator}
* method of {@link #entrySet}. In many cases, you may wish to override
* {@link #clear} to forward to this implementation.
*
* @since 7.0
*/
protected void standardClear() {
Iterators.clear(entrySet().iterator());
}
/**
* A sensible implementation of {@link Map#keySet} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
* {@link ForwardingMap#isEmpty}, {@link ForwardingMap#remove},
* {@link ForwardingMap#size}, and the {@link Set#iterator} method of
* {@link ForwardingMap#entrySet}. In many cases, you may wish to override
* {@link ForwardingMap#keySet} to forward to this implementation or a subclass
* thereof.
*
* @since 10.0
*/
@Beta
protected class StandardKeySet extends Maps.KeySet<K, V> {
/** Constructor for use by subclasses. */
public StandardKeySet() {
super(ForwardingMap.this);
}
}
/**
* A sensible, albeit inefficient, definition of {@link #containsKey} in terms
* of the {@code iterator} method of {@link #entrySet}. If you override
* {@link #entrySet}, you may wish to override {@link #containsKey} to forward
* to this implementation.
*
* @since 7.0
*/
@Beta
protected boolean standardContainsKey(@Nullable Object key) {
return Maps.containsKeyImpl(this, key);
}
/**
* A sensible implementation of {@link Map#values} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsValue},
* {@link ForwardingMap#isEmpty}, {@link ForwardingMap#size}, and the
* {@link Set#iterator} method of {@link ForwardingMap#entrySet}. In many cases,
* you may wish to override {@link ForwardingMap#values} to forward to this
* implementation or a subclass thereof.
*
* @since 10.0
*/
@Beta
protected class StandardValues extends Maps.Values<K, V> {
/** Constructor for use by subclasses. */
public StandardValues() {
super(ForwardingMap.this);
}
}
/**
* A sensible definition of {@link #containsValue} in terms of the {@code
* iterator} method of {@link #entrySet}. If you override {@link #entrySet}, you
* may wish to override {@link #containsValue} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardContainsValue(@Nullable Object value) {
return Maps.containsValueImpl(this, value);
}
/**
* A sensible implementation of {@link Map#entrySet} in terms of the following
* methods: {@link ForwardingMap#clear}, {@link ForwardingMap#containsKey},
* {@link ForwardingMap#get}, {@link ForwardingMap#isEmpty},
* {@link ForwardingMap#remove}, and {@link ForwardingMap#size}. In many cases,
* you may wish to override {@link #entrySet} to forward to this implementation
* or a subclass thereof.
*
* @since 10.0
*/
@Beta
protected abstract class StandardEntrySet extends Maps.EntrySet<K, V> {
/** Constructor for use by subclasses. */
public StandardEntrySet() {
}
@Override
Map<K, V> map() {
return ForwardingMap.this;
}
}
/**
* A sensible definition of {@link #isEmpty} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may wish
* to override {@link #isEmpty} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardIsEmpty() {
return !entrySet().iterator().hasNext();
}
/**
* A sensible definition of {@link #equals} in terms of the {@code equals}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may wish
* to override {@link #equals} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardEquals(@Nullable Object object) {
return Maps.equalsImpl(this, object);
}
/**
* A sensible definition of {@link #hashCode} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may wish
* to override {@link #hashCode} to forward to this implementation.
*
* @since 7.0
*/
protected int standardHashCode() {
return Sets.hashCodeImpl(entrySet());
}
/**
* A sensible definition of {@link #toString} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may wish
* to override {@link #toString} to forward to this implementation.
*
* @since 7.0
*/
protected String standardToString() {
return Maps.toStringImpl(this);
}
}

View File

@ -0,0 +1,134 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map;
import java.util.Map.Entry;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* A map entry which forwards all its method calls to another map entry.
* Subclasses should override one or more methods to modify the behavior of the
* backing map entry as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingMapEntry} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #getValue} alone <i>will not</i> change the behavior of
* {@link #equals}, which can lead to unexpected behavior. In this case, you
* should override {@code equals} as well, either providing your own
* implementation, or delegating to the provided {@code standardEquals} method.
*
* <p>
* Each of the {@code standard} methods, where appropriate, use
* {@link Objects#equal} to test equality for both keys and values. This may not
* be the desired behavior for map implementations that use non-standard notions
* of key equality, such as the entry of a {@code SortedMap} whose comparator is
* not consistent with {@code equals}.
*
* <p>
* The {@code standard} methods are not guaranteed to be thread-safe, even when
* all of the methods that they depend on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingMapEntry<K, V> extends ForwardingObject implements Map.Entry<K, V> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingMapEntry() {
}
@Override
protected abstract Map.Entry<K, V> delegate();
@Override
public K getKey() {
return delegate().getKey();
}
@Override
public V getValue() {
return delegate().getValue();
}
@Override
public V setValue(V value) {
return delegate().setValue(value);
}
@Override
public boolean equals(@Nullable Object object) {
return delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #equals(Object)} in terms of
* {@link #getKey()} and {@link #getValue()}. If you override either of these
* methods, you may wish to override {@link #equals(Object)} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardEquals(@Nullable Object object) {
if (object instanceof Entry) {
Entry<?, ?> that = (Entry<?, ?>) object;
return Objects.equal(this.getKey(), that.getKey()) && Objects.equal(this.getValue(), that.getValue());
}
return false;
}
/**
* A sensible definition of {@link #hashCode()} in terms of {@link #getKey()}
* and {@link #getValue()}. If you override either of these methods, you may
* wish to override {@link #hashCode()} to forward to this implementation.
*
* @since 7.0
*/
protected int standardHashCode() {
K k = getKey();
V v = getValue();
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
/**
* A sensible definition of {@link #toString} in terms of {@link #getKey} and
* {@link #getValue}. If you override either of these methods, you may wish to
* override {@link #equals} to forward to this implementation.
*
* @since 7.0
*/
@Beta
protected String standardToString() {
return getKey() + "=" + getValue();
}
}

View File

@ -0,0 +1,147 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A multimap which forwards all its method calls to another multimap.
* Subclasses should override one or more methods to modify the behavior of the
* backing multimap as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Robert Konigsberg
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingMultimap<K, V> extends ForwardingObject implements Multimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingMultimap() {
}
@Override
protected abstract Multimap<K, V> delegate();
@Override
public Map<K, Collection<V>> asMap() {
return delegate().asMap();
}
@Override
public void clear() {
delegate().clear();
}
@Override
public boolean containsEntry(@Nullable Object key, @Nullable Object value) {
return delegate().containsEntry(key, value);
}
@Override
public boolean containsKey(@Nullable Object key) {
return delegate().containsKey(key);
}
@Override
public boolean containsValue(@Nullable Object value) {
return delegate().containsValue(value);
}
@Override
public Collection<Entry<K, V>> entries() {
return delegate().entries();
}
@Override
public Collection<V> get(@Nullable K key) {
return delegate().get(key);
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public Multiset<K> keys() {
return delegate().keys();
}
@Override
public Set<K> keySet() {
return delegate().keySet();
}
@Override
public boolean put(K key, V value) {
return delegate().put(key, value);
}
@Override
public boolean putAll(K key, Iterable<? extends V> values) {
return delegate().putAll(key, values);
}
@Override
public boolean putAll(Multimap<? extends K, ? extends V> multimap) {
return delegate().putAll(multimap);
}
@Override
public boolean remove(@Nullable Object key, @Nullable Object value) {
return delegate().remove(key, value);
}
@Override
public Collection<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
@Override
public Collection<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
@Override
public int size() {
return delegate().size();
}
@Override
public Collection<V> values() {
return delegate().values();
}
@Override
public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
}

View File

@ -0,0 +1,321 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* A multiset which forwards all its method calls to another multiset.
* Subclasses should override one or more methods to modify the behavior of the
* backing multiset as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingMultiset} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add(Object, int)} alone <b>will not</b> change the
* behavior of {@link #add(Object)}, which can lead to unexpected behavior. In
* this case, you should override {@code add(Object)} as well, either providing
* your own implementation, or delegating to the provided {@code standardAdd}
* method.
*
* <p>
* The {@code standard} methods and any collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingMultiset<E> extends ForwardingCollection<E> implements Multiset<E> {
/** Constructor for use by subclasses. */
protected ForwardingMultiset() {
}
@Override
protected abstract Multiset<E> delegate();
@Override
public int count(Object element) {
return delegate().count(element);
}
@Override
public int add(E element, int occurrences) {
return delegate().add(element, occurrences);
}
@Override
public int remove(Object element, int occurrences) {
return delegate().remove(element, occurrences);
}
@Override
public Set<E> elementSet() {
return delegate().elementSet();
}
@Override
public Set<Entry<E>> entrySet() {
return delegate().entrySet();
}
@Override
public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
@Override
public int setCount(E element, int count) {
return delegate().setCount(element, count);
}
@Override
public boolean setCount(E element, int oldCount, int newCount) {
return delegate().setCount(element, oldCount, newCount);
}
/**
* A sensible definition of {@link #contains} in terms of {@link #count}. If you
* override {@link #count}, you may wish to override {@link #contains} to
* forward to this implementation.
*
* @since 7.0
*/
@Override
protected boolean standardContains(@Nullable Object object) {
return count(object) > 0;
}
/**
* A sensible definition of {@link #clear} in terms of the {@code iterator}
* method of {@link #entrySet}. If you override {@link #entrySet}, you may wish
* to override {@link #clear} to forward to this implementation.
*
* @since 7.0
*/
@Override
protected void standardClear() {
Iterators.clear(entrySet().iterator());
}
/**
* A sensible, albeit inefficient, definition of {@link #count} in terms of
* {@link #entrySet}. If you override {@link #entrySet}, you may wish to
* override {@link #count} to forward to this implementation.
*
* @since 7.0
*/
@Beta
protected int standardCount(@Nullable Object object) {
for (Entry<?> entry : this.entrySet()) {
if (Objects.equal(entry.getElement(), object)) {
return entry.getCount();
}
}
return 0;
}
/**
* A sensible definition of {@link #add(Object)} in terms of
* {@link #add(Object, int)}. If you override {@link #add(Object, int)}, you may
* wish to override {@link #add(Object)} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardAdd(E element) {
add(element, 1);
return true;
}
/**
* A sensible definition of {@link #addAll(Collection)} in terms of
* {@link #add(Object)} and {@link #add(Object, int)}. If you override either of
* these methods, you may wish to override {@link #addAll(Collection)} to
* forward to this implementation.
*
* @since 7.0
*/
@Beta
@Override
protected boolean standardAddAll(Collection<? extends E> elementsToAdd) {
return Multisets.addAllImpl(this, elementsToAdd);
}
/**
* A sensible definition of {@link #remove(Object)} in terms of
* {@link #remove(Object, int)}. If you override {@link #remove(Object, int)},
* you may wish to override {@link #remove(Object)} to forward to this
* implementation.
*
* @since 7.0
*/
@Override
protected boolean standardRemove(Object element) {
return remove(element, 1) > 0;
}
/**
* A sensible definition of {@link #removeAll} in terms of the {@code
* removeAll} method of {@link #elementSet}. If you override
* {@link #elementSet}, you may wish to override {@link #removeAll} to forward
* to this implementation.
*
* @since 7.0
*/
@Override
protected boolean standardRemoveAll(Collection<?> elementsToRemove) {
return Multisets.removeAllImpl(this, elementsToRemove);
}
/**
* A sensible definition of {@link #retainAll} in terms of the {@code
* retainAll} method of {@link #elementSet}. If you override
* {@link #elementSet}, you may wish to override {@link #retainAll} to forward
* to this implementation.
*
* @since 7.0
*/
@Override
protected boolean standardRetainAll(Collection<?> elementsToRetain) {
return Multisets.retainAllImpl(this, elementsToRetain);
}
/**
* A sensible definition of {@link #setCount(Object, int)} in terms of
* {@link #count(Object)}, {@link #add(Object, int)}, and
* {@link #remove(Object, int)}. {@link #entrySet()}. If you override any of
* these methods, you may wish to override {@link #setCount(Object, int)} to
* forward to this implementation.
*
* @since 7.0
*/
protected int standardSetCount(E element, int count) {
return Multisets.setCountImpl(this, element, count);
}
/**
* A sensible definition of {@link #setCount(Object, int, int)} in terms of
* {@link #count(Object)} and {@link #setCount(Object, int)}. If you override
* either of these methods, you may wish to override
* {@link #setCount(Object, int, int)} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardSetCount(E element, int oldCount, int newCount) {
return Multisets.setCountImpl(this, element, oldCount, newCount);
}
/**
* A sensible implementation of {@link Multiset#elementSet} in terms of the
* following methods: {@link ForwardingMultiset#clear},
* {@link ForwardingMultiset#contains}, {@link ForwardingMultiset#containsAll},
* {@link ForwardingMultiset#count}, {@link ForwardingMultiset#isEmpty}, the
* {@link Set#size} and {@link Set#iterator} methods of
* {@link ForwardingMultiset#entrySet}, and
* {@link ForwardingMultiset#remove(Object, int)}. In many situations, you may
* wish to override {@link ForwardingMultiset#elementSet} to forward to this
* implementation or a subclass thereof.
*
* @since 10.0
*/
@Beta
protected class StandardElementSet extends Multisets.ElementSet<E> {
/** Constructor for use by subclasses. */
public StandardElementSet() {
}
@Override
Multiset<E> multiset() {
return ForwardingMultiset.this;
}
}
/**
* A sensible definition of {@link #iterator} in terms of {@link #entrySet} and
* {@link #remove(Object)}. If you override either of these methods, you may
* wish to override {@link #iterator} to forward to this implementation.
*
* @since 7.0
*/
protected Iterator<E> standardIterator() {
return Multisets.iteratorImpl(this);
}
/**
* A sensible, albeit inefficient, definition of {@link #size} in terms of
* {@link #entrySet}. If you override {@link #entrySet}, you may wish to
* override {@link #size} to forward to this implementation.
*
* @since 7.0
*/
protected int standardSize() {
return Multisets.sizeImpl(this);
}
/**
* A sensible, albeit inefficient, definition of {@link #size} in terms of
* {@code entrySet().size()} and {@link #count}. If you override either of these
* methods, you may wish to override {@link #size} to forward to this
* implementation.
*
* @since 7.0
*/
protected boolean standardEquals(@Nullable Object object) {
return Multisets.equalsImpl(this, object);
}
/**
* A sensible definition of {@link #hashCode} as {@code entrySet().hashCode()} .
* If you override {@link #entrySet}, you may wish to override {@link #hashCode}
* to forward to this implementation.
*
* @since 7.0
*/
protected int standardHashCode() {
return entrySet().hashCode();
}
/**
* A sensible definition of {@link #toString} as {@code entrySet().toString()} .
* If you override {@link #entrySet}, you may wish to override {@link #toString}
* to forward to this implementation.
*
* @since 7.0
*/
@Override
protected String standardToString() {
return entrySet().toString();
}
}

View File

@ -0,0 +1,420 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import static com.google.common.collect.Maps.keyOrNull;
import java.util.Iterator;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import com.google.common.annotations.Beta;
/**
* A navigable map which forwards all its method calls to another navigable map.
* Subclasses should override one or more methods to modify the behavior of the
* backing map as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingNavigableMap} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #put} alone <i>will not</i> change the behavior of
* {@link #putAll}, which can lead to unexpected behavior. In this case, you
* should override {@code putAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardPutAll} method.
*
* <p>
* Each of the {@code standard} methods uses the map's comparator (or the
* natural ordering of the elements, if there is no comparator) to test element
* equality. As a result, if the comparator is not consistent with equals, some
* of the standard implementations may violate the {@code Map} contract.
*
* <p>
* The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Louis Wasserman
* @since 12.0
*/
public abstract class ForwardingNavigableMap<K, V> extends ForwardingSortedMap<K, V> implements NavigableMap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingNavigableMap() {
}
@Override
protected abstract NavigableMap<K, V> delegate();
@Override
public Entry<K, V> lowerEntry(K key) {
return delegate().lowerEntry(key);
}
/**
* A sensible definition of {@link #lowerEntry} in terms of the
* {@code lastEntry()} of {@link #headMap(Object, boolean)}. If you override
* {@code headMap}, you may wish to override {@code lowerEntry} to forward to
* this implementation.
*/
protected Entry<K, V> standardLowerEntry(K key) {
return headMap(key, false).lastEntry();
}
@Override
public K lowerKey(K key) {
return delegate().lowerKey(key);
}
/**
* A sensible definition of {@link #lowerKey} in terms of {@code lowerEntry}. If
* you override {@link #lowerEntry}, you may wish to override {@code lowerKey}
* to forward to this implementation.
*/
protected K standardLowerKey(K key) {
return keyOrNull(lowerEntry(key));
}
@Override
public Entry<K, V> floorEntry(K key) {
return delegate().floorEntry(key);
}
/**
* A sensible definition of {@link #floorEntry} in terms of the
* {@code lastEntry()} of {@link #headMap(Object, boolean)}. If you override
* {@code headMap}, you may wish to override {@code floorEntry} to forward to
* this implementation.
*/
protected Entry<K, V> standardFloorEntry(K key) {
return headMap(key, true).lastEntry();
}
@Override
public K floorKey(K key) {
return delegate().floorKey(key);
}
/**
* A sensible definition of {@link #floorKey} in terms of {@code floorEntry}. If
* you override {@code floorEntry}, you may wish to override {@code floorKey} to
* forward to this implementation.
*/
protected K standardFloorKey(K key) {
return keyOrNull(floorEntry(key));
}
@Override
public Entry<K, V> ceilingEntry(K key) {
return delegate().ceilingEntry(key);
}
/**
* A sensible definition of {@link #ceilingEntry} in terms of the
* {@code firstEntry()} of {@link #tailMap(Object, boolean)}. If you override
* {@code tailMap}, you may wish to override {@code ceilingEntry} to forward to
* this implementation.
*/
protected Entry<K, V> standardCeilingEntry(K key) {
return tailMap(key, true).firstEntry();
}
@Override
public K ceilingKey(K key) {
return delegate().ceilingKey(key);
}
/**
* A sensible definition of {@link #ceilingKey} in terms of
* {@code ceilingEntry}. If you override {@code ceilingEntry}, you may wish to
* override {@code ceilingKey} to forward to this implementation.
*/
protected K standardCeilingKey(K key) {
return keyOrNull(ceilingEntry(key));
}
@Override
public Entry<K, V> higherEntry(K key) {
return delegate().higherEntry(key);
}
/**
* A sensible definition of {@link #higherEntry} in terms of the
* {@code firstEntry()} of {@link #tailMap(Object, boolean)}. If you override
* {@code tailMap}, you may wish to override {@code higherEntry} to forward to
* this implementation.
*/
protected Entry<K, V> standardHigherEntry(K key) {
return tailMap(key, false).firstEntry();
}
@Override
public K higherKey(K key) {
return delegate().higherKey(key);
}
/**
* A sensible definition of {@link #higherKey} in terms of {@code higherEntry}.
* If you override {@code higherEntry}, you may wish to override
* {@code higherKey} to forward to this implementation.
*/
protected K standardHigherKey(K key) {
return keyOrNull(higherEntry(key));
}
@Override
public Entry<K, V> firstEntry() {
return delegate().firstEntry();
}
/**
* A sensible definition of {@link #firstEntry} in terms of the
* {@code iterator()} of {@link #entrySet}. If you override {@code entrySet},
* you may wish to override {@code firstEntry} to forward to this
* implementation.
*/
protected Entry<K, V> standardFirstEntry() {
return Iterables.getFirst(entrySet(), null);
}
/**
* A sensible definition of {@link #firstKey} in terms of {@code firstEntry}. If
* you override {@code firstEntry}, you may wish to override {@code firstKey} to
* forward to this implementation.
*/
protected K standardFirstKey() {
Entry<K, V> entry = firstEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
public Entry<K, V> lastEntry() {
return delegate().lastEntry();
}
/**
* A sensible definition of {@link #lastEntry} in terms of the
* {@code iterator()} of the {@link #entrySet} of {@link #descendingMap}. If you
* override {@code descendingMap}, you may wish to override {@code lastEntry} to
* forward to this implementation.
*/
protected Entry<K, V> standardLastEntry() {
return Iterables.getFirst(descendingMap().entrySet(), null);
}
/**
* A sensible definition of {@link #lastKey} in terms of {@code lastEntry}. If
* you override {@code lastEntry}, you may wish to override {@code lastKey} to
* forward to this implementation.
*/
protected K standardLastKey() {
Entry<K, V> entry = lastEntry();
if (entry == null) {
throw new NoSuchElementException();
} else {
return entry.getKey();
}
}
@Override
public Entry<K, V> pollFirstEntry() {
return delegate().pollFirstEntry();
}
/**
* A sensible definition of {@link #pollFirstEntry} in terms of the
* {@code iterator} of {@code entrySet}. If you override {@code entrySet}, you
* may wish to override {@code pollFirstEntry} to forward to this
* implementation.
*/
protected Entry<K, V> standardPollFirstEntry() {
return Iterators.pollNext(entrySet().iterator());
}
@Override
public Entry<K, V> pollLastEntry() {
return delegate().pollLastEntry();
}
/**
* A sensible definition of {@link #pollFirstEntry} in terms of the
* {@code iterator} of the {@code entrySet} of {@code descendingMap}. If you
* override {@code descendingMap}, you may wish to override
* {@code pollFirstEntry} to forward to this implementation.
*/
protected Entry<K, V> standardPollLastEntry() {
return Iterators.pollNext(descendingMap().entrySet().iterator());
}
@Override
public NavigableMap<K, V> descendingMap() {
return delegate().descendingMap();
}
/**
* A sensible implementation of {@link NavigableMap#descendingMap} in terms of
* the methods of this {@code NavigableMap}. In many cases, you may wish to
* override {@link ForwardingNavigableMap#descendingMap} to forward to this
* implementation or a subclass thereof.
*
* <p>
* In particular, this map iterates over entries with repeated calls to
* {@link NavigableMap#lowerEntry}. If a more efficient means of iteration is
* available, you may wish to override the {@code entryIterator()} method of
* this class.
*
* @since 12.0
*/
@Beta
protected class StandardDescendingMap extends Maps.DescendingMap<K, V> {
/** Constructor for use by subclasses. */
public StandardDescendingMap() {
}
@Override
NavigableMap<K, V> forward() {
return ForwardingNavigableMap.this;
}
@Override
protected Iterator<Entry<K, V>> entryIterator() {
return new Iterator<Entry<K, V>>() {
private Entry<K, V> toRemove = null;
private Entry<K, V> nextOrNull = forward().lastEntry();
@Override
public boolean hasNext() {
return nextOrNull != null;
}
@Override
public java.util.Map.Entry<K, V> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return nextOrNull;
} finally {
toRemove = nextOrNull;
nextOrNull = forward().lowerEntry(nextOrNull.getKey());
}
}
@Override
public void remove() {
checkRemove(toRemove != null);
forward().remove(toRemove.getKey());
toRemove = null;
}
};
}
}
@Override
public NavigableSet<K> navigableKeySet() {
return delegate().navigableKeySet();
}
/**
* A sensible implementation of {@link NavigableMap#navigableKeySet} in terms of
* the methods of this {@code NavigableMap}. In many cases, you may wish to
* override {@link ForwardingNavigableMap#navigableKeySet} to forward to this
* implementation or a subclass thereof.
*
* @since 12.0
*/
@Beta
protected class StandardNavigableKeySet extends Maps.NavigableKeySet<K, V> {
/** Constructor for use by subclasses. */
public StandardNavigableKeySet() {
super(ForwardingNavigableMap.this);
}
}
@Override
public NavigableSet<K> descendingKeySet() {
return delegate().descendingKeySet();
}
/**
* A sensible definition of {@link #descendingKeySet} as the
* {@code navigableKeySet} of {@link #descendingMap}. (The
* {@link StandardDescendingMap} implementation implements
* {@code navigableKeySet} on its own, so as not to cause an infinite loop.) If
* you override {@code descendingMap}, you may wish to override
* {@code descendingKeySet} to forward to this implementation.
*/
@Beta
protected NavigableSet<K> standardDescendingKeySet() {
return descendingMap().navigableKeySet();
}
/**
* A sensible definition of {@link #subMap(Object, Object)} in terms of
* {@link #subMap(Object, boolean, Object, boolean)}. If you override
* {@code subMap(K, boolean, K, boolean)}, you may wish to override
* {@code subMap} to forward to this implementation.
*/
@Override
protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
return subMap(fromKey, true, toKey, false);
}
@Override
public NavigableMap<K, V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
return delegate().subMap(fromKey, fromInclusive, toKey, toInclusive);
}
@Override
public NavigableMap<K, V> headMap(K toKey, boolean inclusive) {
return delegate().headMap(toKey, inclusive);
}
@Override
public NavigableMap<K, V> tailMap(K fromKey, boolean inclusive) {
return delegate().tailMap(fromKey, inclusive);
}
/**
* A sensible definition of {@link #headMap(Object)} in terms of
* {@link #headMap(Object, boolean)}. If you override
* {@code headMap(K, boolean)}, you may wish to override {@code headMap} to
* forward to this implementation.
*/
protected SortedMap<K, V> standardHeadMap(K toKey) {
return headMap(toKey, false);
}
/**
* A sensible definition of {@link #tailMap(Object)} in terms of
* {@link #tailMap(Object, boolean)}. If you override
* {@code tailMap(K, boolean)}, you may wish to override {@code tailMap} to
* forward to this implementation.
*/
protected SortedMap<K, V> standardTailMap(K fromKey) {
return tailMap(fromKey, true);
}
}

View File

@ -0,0 +1,246 @@
/*
* Copyright (C) 2012 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.SortedSet;
import com.google.common.annotations.Beta;
/**
* A navigable set which forwards all its method calls to another navigable set.
* Subclasses should override one or more methods to modify the behavior of the
* backing set as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingNavigableSet} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #add} alone <i>will not</i> change the behavior of
* {@link #addAll}, which can lead to unexpected behavior. In this case, you
* should override {@code addAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardAddAll} method.
*
* <p>
* Each of the {@code standard} methods uses the set's comparator (or the
* natural ordering of the elements, if there is no comparator) to test element
* equality. As a result, if the comparator is not consistent with equals, some
* of the standard implementations may violate the {@code Set} contract.
*
* <p>
* The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Louis Wasserman
* @since 12.0
*/
public abstract class ForwardingNavigableSet<E> extends ForwardingSortedSet<E> implements NavigableSet<E> {
/** Constructor for use by subclasses. */
protected ForwardingNavigableSet() {
}
@Override
protected abstract NavigableSet<E> delegate();
@Override
public E lower(E e) {
return delegate().lower(e);
}
/**
* A sensible definition of {@link #lower} in terms of the
* {@code descendingIterator} method of {@link #headSet(Object, boolean)}. If
* you override {@link #headSet(Object, boolean)}, you may wish to override
* {@link #lower} to forward to this implementation.
*/
protected E standardLower(E e) {
return Iterators.getNext(headSet(e, false).descendingIterator(), null);
}
@Override
public E floor(E e) {
return delegate().floor(e);
}
/**
* A sensible definition of {@link #floor} in terms of the
* {@code descendingIterator} method of {@link #headSet(Object, boolean)}. If
* you override {@link #headSet(Object, boolean)}, you may wish to override
* {@link #floor} to forward to this implementation.
*/
protected E standardFloor(E e) {
return Iterators.getNext(headSet(e, true).descendingIterator(), null);
}
@Override
public E ceiling(E e) {
return delegate().ceiling(e);
}
/**
* A sensible definition of {@link #ceiling} in terms of the {@code iterator}
* method of {@link #tailSet(Object, boolean)}. If you override
* {@link #tailSet(Object, boolean)}, you may wish to override {@link #ceiling}
* to forward to this implementation.
*/
protected E standardCeiling(E e) {
return Iterators.getNext(tailSet(e, true).iterator(), null);
}
@Override
public E higher(E e) {
return delegate().higher(e);
}
/**
* A sensible definition of {@link #higher} in terms of the {@code iterator}
* method of {@link #tailSet(Object, boolean)}. If you override
* {@link #tailSet(Object, boolean)}, you may wish to override {@link #higher}
* to forward to this implementation.
*/
protected E standardHigher(E e) {
return Iterators.getNext(tailSet(e, false).iterator(), null);
}
@Override
public E pollFirst() {
return delegate().pollFirst();
}
/**
* A sensible definition of {@link #pollFirst} in terms of the {@code iterator}
* method. If you override {@link #iterator} you may wish to override
* {@link #pollFirst} to forward to this implementation.
*/
protected E standardPollFirst() {
return Iterators.pollNext(iterator());
}
@Override
public E pollLast() {
return delegate().pollLast();
}
/**
* A sensible definition of {@link #pollLast} in terms of the
* {@code descendingIterator} method. If you override
* {@link #descendingIterator} you may wish to override {@link #pollLast} to
* forward to this implementation.
*/
protected E standardPollLast() {
return Iterators.pollNext(descendingIterator());
}
protected E standardFirst() {
return iterator().next();
}
protected E standardLast() {
return descendingIterator().next();
}
@Override
public NavigableSet<E> descendingSet() {
return delegate().descendingSet();
}
/**
* A sensible implementation of {@link NavigableSet#descendingSet} in terms of
* the other methods of {@link NavigableSet}, notably including
* {@link NavigableSet#descendingIterator}.
*
* <p>
* In many cases, you may wish to override
* {@link ForwardingNavigableSet#descendingSet} to forward to this
* implementation or a subclass thereof.
*
* @since 12.0
*/
@Beta
protected class StandardDescendingSet extends Sets.DescendingSet<E> {
/** Constructor for use by subclasses. */
public StandardDescendingSet() {
super(ForwardingNavigableSet.this);
}
}
@Override
public Iterator<E> descendingIterator() {
return delegate().descendingIterator();
}
@Override
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return delegate().subSet(fromElement, fromInclusive, toElement, toInclusive);
}
/**
* A sensible definition of {@link #subSet(Object, boolean, Object, boolean)} in
* terms of the {@code headSet} and {@code tailSet} methods. In many cases, you
* may wish to override {@link #subSet(Object, boolean, Object, boolean)} to
* forward to this implementation.
*/
@Beta
protected NavigableSet<E> standardSubSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return tailSet(fromElement, fromInclusive).headSet(toElement, toInclusive);
}
/**
* A sensible definition of {@link #subSet(Object, Object)} in terms of the
* {@link #subSet(Object, boolean, Object, boolean)} method. If you override
* {@link #subSet(Object, boolean, Object, boolean)}, you may wish to override
* {@link #subSet(Object, Object)} to forward to this implementation.
*/
@Override
protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
return subSet(fromElement, true, toElement, false);
}
@Override
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
return delegate().headSet(toElement, inclusive);
}
/**
* A sensible definition of {@link #headSet(Object)} in terms of the
* {@link #headSet(Object, boolean)} method. If you override
* {@link #headSet(Object, boolean)}, you may wish to override
* {@link #headSet(Object)} to forward to this implementation.
*/
protected SortedSet<E> standardHeadSet(E toElement) {
return headSet(toElement, false);
}
@Override
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
return delegate().tailSet(fromElement, inclusive);
}
/**
* A sensible definition of {@link #tailSet(Object)} in terms of the
* {@link #tailSet(Object, boolean)} method. If you override
* {@link #tailSet(Object, boolean)}, you may wish to override
* {@link #tailSet(Object)} to forward to this implementation.
*/
protected SortedSet<E> standardTailSet(E fromElement) {
return tailSet(fromElement, true);
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.Serializable;
import com.google.common.annotations.GwtCompatible;
/**
* An abstract base class for implementing the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>. The {@link #delegate()} method must be overridden to return the
* instance being decorated.
*
* <p>
* This class does <i>not</i> forward the {@code hashCode} and {@code equals}
* methods through to the backing object, but relies on {@code Object}'s
* implementation. This is necessary to preserve the symmetry of {@code equals}.
* Custom definitions of equality are usually based on an interface, such as
* {@code Set} or {@code List}, so that the implementation of {@code equals} can
* cast the object being tested for equality to the custom interface. {@code
* ForwardingObject} implements no such custom interfaces directly; they are
* implemented only in subclasses. Therefore, forwarding {@code equals} would
* break symmetry, as the forwarding object might consider itself equal to the
* object being tested, but the reverse could not be true. This behavior is
* consistent with the JDK's collection wrappers, such as
* {@link java.util.Collections#unmodifiableCollection}. Use an
* interface-specific subclass of {@code ForwardingObject}, such as
* {@link ForwardingList}, to preserve equality behavior, or override
* {@code equals} directly.
*
* <p>
* The {@code toString} method is forwarded to the delegate. Although this class
* does not implement {@link Serializable}, a serializable subclass may be
* created since this class has a parameter-less constructor.
*
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingObject {
/** Constructor for use by subclasses. */
protected ForwardingObject() {
}
/**
* Returns the backing delegate instance that methods are forwarded to. Abstract
* subclasses generally override this method with an abstract method that has a
* more specific return type, such as {@link ForwardingSet#delegate}. Concrete
* subclasses override this method to supply the instance being decorated.
*/
protected abstract Object delegate();
/**
* Returns the string representation generated by the delegate's
* {@code toString} method.
*/
@Override
public String toString() {
return delegate().toString();
}
/* No equals or hashCode. See class comments for details. */
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.NoSuchElementException;
import java.util.Queue;
import com.google.common.annotations.GwtCompatible;
/**
* A queue which forwards all its method calls to another queue. Subclasses
* should override one or more methods to modify the behavior of the backing
* queue as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingQueue} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of
* {@link #offer} which can lead to unexpected behavior. In this case, you
* should override {@code offer} as well, either providing your own
* implementation, or delegating to the provided {@code standardOffer} method.
*
* <p>
* The {@code standard} methods are not guaranteed to be thread-safe, even when
* all of the methods that they depend on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingQueue<E> extends ForwardingCollection<E> implements Queue<E> {
/** Constructor for use by subclasses. */
protected ForwardingQueue() {
}
@Override
protected abstract Queue<E> delegate();
@Override
public boolean offer(E o) {
return delegate().offer(o);
}
@Override
public E poll() {
return delegate().poll();
}
@Override
public E remove() {
return delegate().remove();
}
@Override
public E peek() {
return delegate().peek();
}
@Override
public E element() {
return delegate().element();
}
/**
* A sensible definition of {@link #offer} in terms of {@link #add}. If you
* override {@link #add}, you may wish to override {@link #offer} to forward to
* this implementation.
*
* @since 7.0
*/
protected boolean standardOffer(E e) {
try {
return add(e);
} catch (IllegalStateException caught) {
return false;
}
}
/**
* A sensible definition of {@link #peek} in terms of {@link #element}. If you
* override {@link #element}, you may wish to override {@link #peek} to forward
* to this implementation.
*
* @since 7.0
*/
protected E standardPeek() {
try {
return element();
} catch (NoSuchElementException caught) {
return null;
}
}
/**
* A sensible definition of {@link #poll} in terms of {@link #remove}. If you
* override {@link #remove}, you may wish to override {@link #poll} to forward
* to this implementation.
*
* @since 7.0
*/
protected E standardPoll() {
try {
return remove();
} catch (NoSuchElementException caught) {
return null;
}
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A set which forwards all its method calls to another set. Subclasses should
* override one or more methods to modify the behavior of the backing set as
* desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingSet} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add} alone <b>will not</b> change the behavior of
* {@link #addAll}, which can lead to unexpected behavior. In this case, you
* should override {@code addAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardAddAll} method.
*
* <p>
* The {@code standard} methods are not guaranteed to be thread-safe, even when
* all of the methods that they depend on are thread-safe.
*
* @author Kevin Bourrillion
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingSet<E> extends ForwardingCollection<E> implements Set<E> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingSet() {
}
@Override
protected abstract Set<E> delegate();
@Override
public boolean equals(@Nullable Object object) {
return object == this || delegate().equals(object);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
/**
* A sensible definition of {@link #removeAll} in terms of {@link #iterator} and
* {@link #remove}. If you override {@code iterator} or {@code remove}, you may
* wish to override {@link #removeAll} to forward to this implementation.
*
* @since 7.0 (this version overrides the {@code ForwardingCollection} version
* as of 12.0)
*/
@Override
protected boolean standardRemoveAll(Collection<?> collection) {
return Sets.removeAllImpl(this, checkNotNull(collection)); // for GWT
}
/**
* A sensible definition of {@link #equals} in terms of {@link #size} and
* {@link #containsAll}. If you override either of those methods, you may wish
* to override {@link #equals} to forward to this implementation.
*
* @since 7.0
*/
protected boolean standardEquals(@Nullable Object object) {
return Sets.equalsImpl(this, object);
}
/**
* A sensible definition of {@link #hashCode} in terms of {@link #iterator}. If
* you override {@link #iterator}, you may wish to override {@link #equals} to
* forward to this implementation.
*
* @since 7.0
*/
protected int standardHashCode() {
return Sets.hashCodeImpl(this);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map.Entry;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A set multimap which forwards all its method calls to another set multimap.
* Subclasses should override one or more methods to modify the behavior of the
* backing multimap as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Kurt Alfred Kluever
* @since 3.0
*/
@GwtCompatible
public abstract class ForwardingSetMultimap<K, V> extends ForwardingMultimap<K, V> implements SetMultimap<K, V> {
@Override
protected abstract SetMultimap<K, V> delegate();
@Override
public Set<Entry<K, V>> entries() {
return delegate().entries();
}
@Override
public Set<V> get(@Nullable K key) {
return delegate().get(key);
}
@Override
public Set<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
@Override
public Set<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
}

View File

@ -0,0 +1,165 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import java.util.Comparator;
import java.util.NoSuchElementException;
import java.util.SortedMap;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A sorted map which forwards all its method calls to another sorted map.
* Subclasses should override one or more methods to modify the behavior of the
* backing sorted map as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingSortedMap} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #put} alone <i>will not</i> change the behavior of
* {@link #putAll}, which can lead to unexpected behavior. In this case, you
* should override {@code putAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardPutAll} method.
*
* <p>
* Each of the {@code standard} methods, where appropriate, use the comparator
* of the map to test equality for both keys and values, unlike
* {@code ForwardingMap}.
*
* <p>
* The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingSortedMap<K, V> extends ForwardingMap<K, V> implements SortedMap<K, V> {
// TODO(user): identify places where thread safety is actually lost
/** Constructor for use by subclasses. */
protected ForwardingSortedMap() {
}
@Override
protected abstract SortedMap<K, V> delegate();
@Override
public Comparator<? super K> comparator() {
return delegate().comparator();
}
@Override
public K firstKey() {
return delegate().firstKey();
}
@Override
public SortedMap<K, V> headMap(K toKey) {
return delegate().headMap(toKey);
}
@Override
public K lastKey() {
return delegate().lastKey();
}
@Override
public SortedMap<K, V> subMap(K fromKey, K toKey) {
return delegate().subMap(fromKey, toKey);
}
@Override
public SortedMap<K, V> tailMap(K fromKey) {
return delegate().tailMap(fromKey);
}
/**
* A sensible implementation of {@link SortedMap#keySet} in terms of the methods
* of {@code ForwardingSortedMap}. In many cases, you may wish to override
* {@link ForwardingSortedMap#keySet} to forward to this implementation or a
* subclass thereof.
*
* @since 15.0
*/
@Beta
protected class StandardKeySet extends Maps.SortedKeySet<K, V> {
/** Constructor for use by subclasses. */
public StandardKeySet() {
super(ForwardingSortedMap.this);
}
}
// unsafe, but worst case is a CCE is thrown, which callers will be expecting
@SuppressWarnings("unchecked")
private int unsafeCompare(Object k1, Object k2) {
Comparator<? super K> comparator = comparator();
if (comparator == null) {
return ((Comparable<Object>) k1).compareTo(k2);
} else {
return ((Comparator<Object>) comparator).compare(k1, k2);
}
}
/**
* A sensible definition of {@link #containsKey} in terms of the {@code
* firstKey()} method of {@link #tailMap}. If you override {@link #tailMap}, you
* may wish to override {@link #containsKey} to forward to this implementation.
*
* @since 7.0
*/
@Override
@Beta
protected boolean standardContainsKey(@Nullable Object key) {
try {
// any CCE will be caught
@SuppressWarnings("unchecked")
SortedMap<Object, V> self = (SortedMap<Object, V>) this;
Object ceilingKey = self.tailMap(key).firstKey();
return unsafeCompare(ceilingKey, key) == 0;
} catch (ClassCastException e) {
return false;
} catch (NoSuchElementException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* A sensible default implementation of {@link #subMap(Object, Object)} in terms
* of {@link #headMap(Object)} and {@link #tailMap(Object)}. In some situations,
* you may wish to override {@link #subMap(Object, Object)} to forward to this
* implementation.
*
* @since 7.0
*/
@Beta
protected SortedMap<K, V> standardSubMap(K fromKey, K toKey) {
checkArgument(unsafeCompare(fromKey, toKey) <= 0, "fromKey must be <= toKey");
return tailMap(fromKey).headMap(toKey);
}
}

View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableSet;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A sorted multiset which forwards all its method calls to another sorted
* multiset. Subclasses should override one or more methods to modify the
* behavior of the backing multiset as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <b>Warning:</b> The methods of {@code ForwardingSortedMultiset} forward
* <b>indiscriminately</b> to the methods of the delegate. For example,
* overriding {@link #add(Object, int)} alone <b>will not</b> change the
* behavior of {@link #add(Object)}, which can lead to unexpected behavior. In
* this case, you should override {@code add(Object)} as well, either providing
* your own implementation, or delegating to the provided {@code
* standardAdd} method.
*
* <p>
* The {@code standard} methods and any collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Louis Wasserman
* @since 15.0
*/
@Beta
@GwtCompatible(emulated = true)
public abstract class ForwardingSortedMultiset<E> extends ForwardingMultiset<E> implements SortedMultiset<E> {
/** Constructor for use by subclasses. */
protected ForwardingSortedMultiset() {
}
@Override
protected abstract SortedMultiset<E> delegate();
@Override
public NavigableSet<E> elementSet() {
return (NavigableSet<E>) super.elementSet();
}
/**
* A sensible implementation of {@link SortedMultiset#elementSet} in terms of
* the following methods: {@link SortedMultiset#clear},
* {@link SortedMultiset#comparator}, {@link SortedMultiset#contains},
* {@link SortedMultiset#containsAll}, {@link SortedMultiset#count},
* {@link SortedMultiset#firstEntry} {@link SortedMultiset#headMultiset},
* {@link SortedMultiset#isEmpty}, {@link SortedMultiset#lastEntry},
* {@link SortedMultiset#subMultiset}, {@link SortedMultiset#tailMultiset}, the
* {@code size()} and {@code iterator()} methods of
* {@link SortedMultiset#entrySet}, and
* {@link SortedMultiset#remove(Object, int)}. In many situations, you may wish
* to override {@link SortedMultiset#elementSet} to forward to this
* implementation or a subclass thereof.
*/
protected class StandardElementSet extends SortedMultisets.NavigableElementSet<E> {
/** Constructor for use by subclasses. */
public StandardElementSet() {
super(ForwardingSortedMultiset.this);
}
}
@Override
public Comparator<? super E> comparator() {
return delegate().comparator();
}
@Override
public SortedMultiset<E> descendingMultiset() {
return delegate().descendingMultiset();
}
/**
* A skeleton implementation of a descending multiset view. Normally,
* {@link #descendingMultiset()} will not reflect any changes you make to the
* behavior of methods such as {@link #add(Object)} or {@link #pollFirstEntry}.
* This skeleton implementation correctly delegates each of its operations to
* the appropriate methods of this {@code
* ForwardingSortedMultiset}.
*
* In many cases, you may wish to override {@link #descendingMultiset()} to
* return an instance of a subclass of {@code StandardDescendingMultiset}.
*/
protected abstract class StandardDescendingMultiset extends DescendingMultiset<E> {
/** Constructor for use by subclasses. */
public StandardDescendingMultiset() {
}
@Override
SortedMultiset<E> forwardMultiset() {
return ForwardingSortedMultiset.this;
}
}
@Override
public Entry<E> firstEntry() {
return delegate().firstEntry();
}
/**
* A sensible definition of {@link #firstEntry()} in terms of
* {@code entrySet().iterator()}.
*
* If you override {@link #entrySet()}, you may wish to override
* {@link #firstEntry()} to forward to this implementation.
*/
protected Entry<E> standardFirstEntry() {
Iterator<Entry<E>> entryIterator = entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
Entry<E> entry = entryIterator.next();
return Multisets.immutableEntry(entry.getElement(), entry.getCount());
}
@Override
public Entry<E> lastEntry() {
return delegate().lastEntry();
}
/**
* A sensible definition of {@link #lastEntry()} in terms of {@code
* descendingMultiset().entrySet().iterator()}.
*
* If you override {@link #descendingMultiset} or {@link #entrySet()}, you may
* wish to override {@link #firstEntry()} to forward to this implementation.
*/
protected Entry<E> standardLastEntry() {
Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
Entry<E> entry = entryIterator.next();
return Multisets.immutableEntry(entry.getElement(), entry.getCount());
}
@Override
public Entry<E> pollFirstEntry() {
return delegate().pollFirstEntry();
}
/**
* A sensible definition of {@link #pollFirstEntry()} in terms of
* {@code entrySet().iterator()}.
*
* If you override {@link #entrySet()}, you may wish to override
* {@link #pollFirstEntry()} to forward to this implementation.
*/
protected Entry<E> standardPollFirstEntry() {
Iterator<Entry<E>> entryIterator = entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
Entry<E> entry = entryIterator.next();
entry = Multisets.immutableEntry(entry.getElement(), entry.getCount());
entryIterator.remove();
return entry;
}
@Override
public Entry<E> pollLastEntry() {
return delegate().pollLastEntry();
}
/**
* A sensible definition of {@link #pollLastEntry()} in terms of {@code
* descendingMultiset().entrySet().iterator()}.
*
* If you override {@link #descendingMultiset()} or {@link #entrySet()}, you may
* wish to override {@link #pollLastEntry()} to forward to this implementation.
*/
protected Entry<E> standardPollLastEntry() {
Iterator<Entry<E>> entryIterator = descendingMultiset().entrySet().iterator();
if (!entryIterator.hasNext()) {
return null;
}
Entry<E> entry = entryIterator.next();
entry = Multisets.immutableEntry(entry.getElement(), entry.getCount());
entryIterator.remove();
return entry;
}
@Override
public SortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
return delegate().headMultiset(upperBound, boundType);
}
@Override
public SortedMultiset<E> subMultiset(E lowerBound, BoundType lowerBoundType, E upperBound,
BoundType upperBoundType) {
return delegate().subMultiset(lowerBound, lowerBoundType, upperBound, upperBoundType);
}
/**
* A sensible definition of
* {@link #subMultiset(Object, BoundType, Object, BoundType)} in terms of
* {@link #headMultiset(Object, BoundType) headMultiset} and
* {@link #tailMultiset(Object, BoundType) tailMultiset}.
*
* If you override either of these methods, you may wish to override
* {@link #subMultiset(Object, BoundType, Object, BoundType)} to forward to this
* implementation.
*/
protected SortedMultiset<E> standardSubMultiset(E lowerBound, BoundType lowerBoundType, E upperBound,
BoundType upperBoundType) {
return tailMultiset(lowerBound, lowerBoundType).headMultiset(upperBound, upperBoundType);
}
@Override
public SortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
return delegate().tailMultiset(lowerBound, boundType);
}
}

View File

@ -0,0 +1,175 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Comparator;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.SortedSet;
import javax.annotation.Nullable;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
/**
* A sorted set which forwards all its method calls to another sorted set.
* Subclasses should override one or more methods to modify the behavior of the
* backing sorted set as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* <p>
* <i>Warning:</i> The methods of {@code ForwardingSortedSet} forward
* <i>indiscriminately</i> to the methods of the delegate. For example,
* overriding {@link #add} alone <i>will not</i> change the behavior of
* {@link #addAll}, which can lead to unexpected behavior. In this case, you
* should override {@code addAll} as well, either providing your own
* implementation, or delegating to the provided {@code standardAddAll} method.
*
* <p>
* Each of the {@code standard} methods, where appropriate, uses the set's
* comparator (or the natural ordering of the elements, if there is no
* comparator) to test element equality. As a result, if the comparator is not
* consistent with equals, some of the standard implementations may violate the
* {@code Set} contract.
*
* <p>
* The {@code standard} methods and the collection views they return are not
* guaranteed to be thread-safe, even when all of the methods that they depend
* on are thread-safe.
*
* @author Mike Bostock
* @author Louis Wasserman
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible
public abstract class ForwardingSortedSet<E> extends ForwardingSet<E> implements SortedSet<E> {
/** Constructor for use by subclasses. */
protected ForwardingSortedSet() {
}
@Override
protected abstract SortedSet<E> delegate();
@Override
public Comparator<? super E> comparator() {
return delegate().comparator();
}
@Override
public E first() {
return delegate().first();
}
@Override
public SortedSet<E> headSet(E toElement) {
return delegate().headSet(toElement);
}
@Override
public E last() {
return delegate().last();
}
@Override
public SortedSet<E> subSet(E fromElement, E toElement) {
return delegate().subSet(fromElement, toElement);
}
@Override
public SortedSet<E> tailSet(E fromElement) {
return delegate().tailSet(fromElement);
}
// unsafe, but worst case is a CCE is thrown, which callers will be expecting
@SuppressWarnings("unchecked")
private int unsafeCompare(Object o1, Object o2) {
Comparator<? super E> comparator = comparator();
return (comparator == null) ? ((Comparable<Object>) o1).compareTo(o2)
: ((Comparator<Object>) comparator).compare(o1, o2);
}
/**
* A sensible definition of {@link #contains} in terms of the {@code first()}
* method of {@link #tailSet}. If you override {@link #tailSet}, you may wish to
* override {@link #contains} to forward to this implementation.
*
* @since 7.0
*/
@Override
@Beta
protected boolean standardContains(@Nullable Object object) {
try {
// any ClassCastExceptions are caught
@SuppressWarnings("unchecked")
SortedSet<Object> self = (SortedSet<Object>) this;
Object ceiling = self.tailSet(object).first();
return unsafeCompare(ceiling, object) == 0;
} catch (ClassCastException e) {
return false;
} catch (NoSuchElementException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
/**
* A sensible definition of {@link #remove} in terms of the {@code iterator()}
* method of {@link #tailSet}. If you override {@link #tailSet}, you may wish to
* override {@link #remove} to forward to this implementation.
*
* @since 7.0
*/
@Override
@Beta
protected boolean standardRemove(@Nullable Object object) {
try {
// any ClassCastExceptions are caught
@SuppressWarnings("unchecked")
SortedSet<Object> self = (SortedSet<Object>) this;
Iterator<Object> iterator = self.tailSet(object).iterator();
if (iterator.hasNext()) {
Object ceiling = iterator.next();
if (unsafeCompare(ceiling, object) == 0) {
iterator.remove();
return true;
}
}
} catch (ClassCastException e) {
return false;
} catch (NullPointerException e) {
return false;
}
return false;
}
/**
* A sensible default implementation of {@link #subSet(Object, Object)} in terms
* of {@link #headSet(Object)} and {@link #tailSet(Object)}. In some situations,
* you may wish to override {@link #subSet(Object, Object)} to forward to this
* implementation.
*
* @since 7.0
*/
@Beta
protected SortedSet<E> standardSubSet(E fromElement, E toElement) {
return tailSet(fromElement).headSet(toElement);
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2010 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Comparator;
import java.util.SortedSet;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* A sorted set multimap which forwards all its method calls to another sorted
* set multimap. Subclasses should override one or more methods to modify the
* behavior of the backing multimap as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Kurt Alfred Kluever
* @since 3.0
*/
@GwtCompatible
public abstract class ForwardingSortedSetMultimap<K, V> extends ForwardingSetMultimap<K, V>
implements SortedSetMultimap<K, V> {
/** Constructor for use by subclasses. */
protected ForwardingSortedSetMultimap() {
}
@Override
protected abstract SortedSetMultimap<K, V> delegate();
@Override
public SortedSet<V> get(@Nullable K key) {
return delegate().get(key);
}
@Override
public SortedSet<V> removeAll(@Nullable Object key) {
return delegate().removeAll(key);
}
@Override
public SortedSet<V> replaceValues(K key, Iterable<? extends V> values) {
return delegate().replaceValues(key, values);
}
@Override
public Comparator<? super V> valueComparator() {
return delegate().valueComparator();
}
}

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import com.google.common.annotations.GwtCompatible;
/**
* A table which forwards all its method calls to another table. Subclasses
* should override one or more methods to modify the behavior of the backing map
* as desired per the
* <a href="http://en.wikipedia.org/wiki/Decorator_pattern">decorator
* pattern</a>.
*
* @author Gregory Kick
* @since 7.0
*/
@GwtCompatible
public abstract class ForwardingTable<R, C, V> extends ForwardingObject implements Table<R, C, V> {
/** Constructor for use by subclasses. */
protected ForwardingTable() {
}
@Override
protected abstract Table<R, C, V> delegate();
@Override
public Set<Cell<R, C, V>> cellSet() {
return delegate().cellSet();
}
@Override
public void clear() {
delegate().clear();
}
@Override
public Map<R, V> column(C columnKey) {
return delegate().column(columnKey);
}
@Override
public Set<C> columnKeySet() {
return delegate().columnKeySet();
}
@Override
public Map<C, Map<R, V>> columnMap() {
return delegate().columnMap();
}
@Override
public boolean contains(Object rowKey, Object columnKey) {
return delegate().contains(rowKey, columnKey);
}
@Override
public boolean containsColumn(Object columnKey) {
return delegate().containsColumn(columnKey);
}
@Override
public boolean containsRow(Object rowKey) {
return delegate().containsRow(rowKey);
}
@Override
public boolean containsValue(Object value) {
return delegate().containsValue(value);
}
@Override
public V get(Object rowKey, Object columnKey) {
return delegate().get(rowKey, columnKey);
}
@Override
public boolean isEmpty() {
return delegate().isEmpty();
}
@Override
public V put(R rowKey, C columnKey, V value) {
return delegate().put(rowKey, columnKey, value);
}
@Override
public void putAll(Table<? extends R, ? extends C, ? extends V> table) {
delegate().putAll(table);
}
@Override
public V remove(Object rowKey, Object columnKey) {
return delegate().remove(rowKey, columnKey);
}
@Override
public Map<C, V> row(R rowKey) {
return delegate().row(rowKey);
}
@Override
public Set<R> rowKeySet() {
return delegate().rowKeySet();
}
@Override
public Map<R, Map<C, V>> rowMap() {
return delegate().rowMap();
}
@Override
public int size() {
return delegate().size();
}
@Override
public Collection<V> values() {
return delegate().values();
}
@Override
public boolean equals(Object obj) {
return (obj == this) || delegate().equals(obj);
}
@Override
public int hashCode() {
return delegate().hashCode();
}
}

View File

@ -0,0 +1,275 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.BoundType.CLOSED;
import static com.google.common.collect.BoundType.OPEN;
import java.io.Serializable;
import java.util.Comparator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
/**
* A generalized interval on any ordering, for internal use. Supports
* {@code null}. Unlike {@link Range}, this allows the use of an arbitrary
* comparator. This is designed for use in the implementation of subcollections
* of sorted collection types.
*
* <p>
* Whenever possible, use {@code Range} instead, which is better supported.
*
* @author Louis Wasserman
*/
@GwtCompatible(serializable = true)
final class GeneralRange<T> implements Serializable {
/**
* Converts a Range to a GeneralRange.
*/
static <T extends Comparable> GeneralRange<T> from(Range<T> range) {
@Nullable
T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN;
@Nullable
T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN;
return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint, lowerBoundType,
range.hasUpperBound(), upperEndpoint, upperBoundType);
}
/**
* Returns the whole range relative to the specified comparator.
*/
static <T> GeneralRange<T> all(Comparator<? super T> comparator) {
return new GeneralRange<T>(comparator, false, null, OPEN, false, null, OPEN);
}
/**
* Returns everything above the endpoint relative to the specified comparator,
* with the specified endpoint behavior.
*/
static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN);
}
/**
* Returns everything below the endpoint relative to the specified comparator,
* with the specified endpoint behavior.
*/
static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint, BoundType boundType) {
return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType);
}
/**
* Returns everything between the endpoints relative to the specified
* comparator, with the specified endpoint behavior.
*/
static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower, BoundType lowerType,
@Nullable T upper, BoundType upperType) {
return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType);
}
private final Comparator<? super T> comparator;
private final boolean hasLowerBound;
@Nullable
private final T lowerEndpoint;
private final BoundType lowerBoundType;
private final boolean hasUpperBound;
@Nullable
private final T upperEndpoint;
private final BoundType upperBoundType;
private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound, @Nullable T lowerEndpoint,
BoundType lowerBoundType, boolean hasUpperBound, @Nullable T upperEndpoint, BoundType upperBoundType) {
this.comparator = checkNotNull(comparator);
this.hasLowerBound = hasLowerBound;
this.hasUpperBound = hasUpperBound;
this.lowerEndpoint = lowerEndpoint;
this.lowerBoundType = checkNotNull(lowerBoundType);
this.upperEndpoint = upperEndpoint;
this.upperBoundType = checkNotNull(upperBoundType);
if (hasLowerBound) {
comparator.compare(lowerEndpoint, lowerEndpoint);
}
if (hasUpperBound) {
comparator.compare(upperEndpoint, upperEndpoint);
}
if (hasLowerBound && hasUpperBound) {
int cmp = comparator.compare(lowerEndpoint, upperEndpoint);
// be consistent with Range
checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint, upperEndpoint);
if (cmp == 0) {
checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN);
}
}
}
Comparator<? super T> comparator() {
return comparator;
}
boolean hasLowerBound() {
return hasLowerBound;
}
boolean hasUpperBound() {
return hasUpperBound;
}
boolean isEmpty() {
return (hasUpperBound() && tooLow(getUpperEndpoint())) || (hasLowerBound() && tooHigh(getLowerEndpoint()));
}
boolean tooLow(@Nullable T t) {
if (!hasLowerBound()) {
return false;
}
T lbound = getLowerEndpoint();
int cmp = comparator.compare(t, lbound);
return cmp < 0 | (cmp == 0 & getLowerBoundType() == OPEN);
}
boolean tooHigh(@Nullable T t) {
if (!hasUpperBound()) {
return false;
}
T ubound = getUpperEndpoint();
int cmp = comparator.compare(t, ubound);
return cmp > 0 | (cmp == 0 & getUpperBoundType() == OPEN);
}
boolean contains(@Nullable T t) {
return !tooLow(t) && !tooHigh(t);
}
/**
* Returns the intersection of the two ranges, or an empty range if their
* intersection is empty.
*/
GeneralRange<T> intersect(GeneralRange<T> other) {
checkNotNull(other);
checkArgument(comparator.equals(other.comparator));
boolean hasLowBound = this.hasLowerBound;
@Nullable
T lowEnd = getLowerEndpoint();
BoundType lowType = getLowerBoundType();
if (!hasLowerBound()) {
hasLowBound = other.hasLowerBound;
lowEnd = other.getLowerEndpoint();
lowType = other.getLowerBoundType();
} else if (other.hasLowerBound()) {
int cmp = comparator.compare(getLowerEndpoint(), other.getLowerEndpoint());
if (cmp < 0 || (cmp == 0 && other.getLowerBoundType() == OPEN)) {
lowEnd = other.getLowerEndpoint();
lowType = other.getLowerBoundType();
}
}
boolean hasUpBound = this.hasUpperBound;
@Nullable
T upEnd = getUpperEndpoint();
BoundType upType = getUpperBoundType();
if (!hasUpperBound()) {
hasUpBound = other.hasUpperBound;
upEnd = other.getUpperEndpoint();
upType = other.getUpperBoundType();
} else if (other.hasUpperBound()) {
int cmp = comparator.compare(getUpperEndpoint(), other.getUpperEndpoint());
if (cmp > 0 || (cmp == 0 && other.getUpperBoundType() == OPEN)) {
upEnd = other.getUpperEndpoint();
upType = other.getUpperBoundType();
}
}
if (hasLowBound && hasUpBound) {
int cmp = comparator.compare(lowEnd, upEnd);
if (cmp > 0 || (cmp == 0 && lowType == OPEN && upType == OPEN)) {
// force allowed empty range
lowEnd = upEnd;
lowType = OPEN;
upType = CLOSED;
}
}
return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType);
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof GeneralRange) {
GeneralRange<?> r = (GeneralRange<?>) obj;
return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound
&& hasUpperBound == r.hasUpperBound && getLowerBoundType().equals(r.getLowerBoundType())
&& getUpperBoundType().equals(r.getUpperBoundType())
&& Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())
&& Objects.equal(getUpperEndpoint(), r.getUpperEndpoint());
}
return false;
}
@Override
public int hashCode() {
return Objects.hashCode(comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(),
getUpperBoundType());
}
private transient GeneralRange<T> reverse;
/**
* Returns the same range relative to the reversed comparator.
*/
GeneralRange<T> reverse() {
GeneralRange<T> result = reverse;
if (result == null) {
result = new GeneralRange<T>(Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(),
getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType());
result.reverse = this;
return this.reverse = result;
}
return result;
}
@Override
public String toString() {
return new StringBuilder().append(comparator).append(":").append(lowerBoundType == CLOSED ? '[' : '(')
.append(hasLowerBound ? lowerEndpoint : "-\u221e").append(',')
.append(hasUpperBound ? upperEndpoint : "\u221e").append(upperBoundType == CLOSED ? ']' : ')')
.toString();
}
T getLowerEndpoint() {
return lowerEndpoint;
}
BoundType getLowerBoundType() {
return lowerBoundType;
}
T getUpperEndpoint() {
return upperEndpoint;
}
BoundType getUpperBoundType() {
return upperBoundType;
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.google.common.annotations.GwtCompatible;
/**
* Private replacement for {@link com.google.gwt.user.client.rpc.GwtTransient}
* to work around build-system quirks. This annotation should be used
* <b>only</b> in {@code com.google.common.collect}.
*/
@Documented
@GwtCompatible
@Retention(RUNTIME)
@Target(FIELD)
@interface GwtTransient {
}

View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Supplier;
/**
* Implementation of {@link Table} using hash tables.
*
* <p>
* The views returned by {@link #column}, {@link #columnKeySet()}, and
* {@link #columnMap()} have iterators that don't support {@code remove()}.
* Otherwise, all optional operations are supported. Null row keys, columns
* keys, and values are not supported.
*
* <p>
* Lookups by row key are often faster than lookups by column key, because the
* data is stored in a {@code Map<R, Map<C, V>>}. A method call like {@code
* column(columnKey).get(rowKey)} still runs quickly, since the row key is
* provided. However, {@code column(columnKey).size()} takes longer, since an
* iteration across all row keys occurs.
*
* <p>
* Note that this implementation is not synchronized. If multiple threads access
* this table concurrently and one of the threads modifies the table, it must be
* synchronized externally.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table">
* {@code Table}</a>.
*
* @author Jared Levy
* @since 7.0
*/
@GwtCompatible(serializable = true)
public class HashBasedTable<R, C, V> extends StandardTable<R, C, V> {
private static class Factory<C, V> implements Supplier<Map<C, V>>, Serializable {
final int expectedSize;
Factory(int expectedSize) {
this.expectedSize = expectedSize;
}
@Override
public Map<C, V> get() {
return Maps.newHashMapWithExpectedSize(expectedSize);
}
private static final long serialVersionUID = 0;
}
/**
* Creates an empty {@code HashBasedTable}.
*/
public static <R, C, V> HashBasedTable<R, C, V> create() {
return new HashBasedTable<R, C, V>(new HashMap<R, Map<C, V>>(), new Factory<C, V>(0));
}
/**
* Creates an empty {@code HashBasedTable} with the specified map sizes.
*
* @param expectedRows the expected number of distinct row keys
* @param expectedCellsPerRow the expected number of column key / value mappings
* in each row
* @throws IllegalArgumentException if {@code expectedRows} or {@code
* expectedCellsPerRow} is negative
*/
public static <R, C, V> HashBasedTable<R, C, V> create(int expectedRows, int expectedCellsPerRow) {
checkNonnegative(expectedCellsPerRow, "expectedCellsPerRow");
Map<R, Map<C, V>> backingMap = Maps.newHashMapWithExpectedSize(expectedRows);
return new HashBasedTable<R, C, V>(backingMap, new Factory<C, V>(expectedCellsPerRow));
}
/**
* Creates a {@code HashBasedTable} with the same mappings as the specified
* table.
*
* @param table the table to copy
* @throws NullPointerException if any of the row keys, column keys, or values
* in {@code table} is null
*/
public static <R, C, V> HashBasedTable<R, C, V> create(Table<? extends R, ? extends C, ? extends V> table) {
HashBasedTable<R, C, V> result = create();
result.putAll(table);
return result;
}
HashBasedTable(Map<R, Map<C, V>> backingMap, Factory<C, V> factory) {
super(backingMap, factory);
}
// Overriding so NullPointerTester test passes.
@Override
public boolean contains(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.contains(rowKey, columnKey);
}
@Override
public boolean containsColumn(@Nullable Object columnKey) {
return super.containsColumn(columnKey);
}
@Override
public boolean containsRow(@Nullable Object rowKey) {
return super.containsRow(rowKey);
}
@Override
public boolean containsValue(@Nullable Object value) {
return super.containsValue(value);
}
@Override
public V get(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.get(rowKey, columnKey);
}
@Override
public boolean equals(@Nullable Object obj) {
return super.equals(obj);
}
@Override
public V remove(@Nullable Object rowKey, @Nullable Object columnKey) {
return super.remove(rowKey, columnKey);
}
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,670 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.CollectPreconditions.checkRemove;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Objects;
/**
* A {@link BiMap} backed by two hash tables. This implementation allows null
* keys and values. A {@code HashBiMap} and its inverse are both serializable.
*
* <p>
* See the Guava User Guide article on <a href=
* "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap">
* {@code BiMap} </a>.
*
* @author Louis Wasserman
* @author Mike Bostock
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
public final class HashBiMap<K, V> extends AbstractMap<K, V> implements BiMap<K, V>, Serializable {
/**
* Returns a new, empty {@code HashBiMap} with the default initial capacity
* (16).
*/
public static <K, V> HashBiMap<K, V> create() {
return create(16);
}
/**
* Constructs a new, empty bimap with the specified expected size.
*
* @param expectedSize the expected number of entries
* @throws IllegalArgumentException if the specified expected size is negative
*/
public static <K, V> HashBiMap<K, V> create(int expectedSize) {
return new HashBiMap<K, V>(expectedSize);
}
/**
* Constructs a new bimap containing initial values from {@code map}. The bimap
* is created with an initial capacity sufficient to hold the mappings in the
* specified map.
*/
public static <K, V> HashBiMap<K, V> create(Map<? extends K, ? extends V> map) {
HashBiMap<K, V> bimap = create(map.size());
bimap.putAll(map);
return bimap;
}
private static final class BiEntry<K, V> extends ImmutableEntry<K, V> {
final int keyHash;
final int valueHash;
@Nullable
BiEntry<K, V> nextInKToVBucket;
@Nullable
BiEntry<K, V> nextInVToKBucket;
BiEntry(K key, int keyHash, V value, int valueHash) {
super(key, value);
this.keyHash = keyHash;
this.valueHash = valueHash;
}
}
private static final double LOAD_FACTOR = 1.0;
private transient BiEntry<K, V>[] hashTableKToV;
private transient BiEntry<K, V>[] hashTableVToK;
private transient int size;
private transient int mask;
private transient int modCount;
private HashBiMap(int expectedSize) {
init(expectedSize);
}
private void init(int expectedSize) {
checkNonnegative(expectedSize, "expectedSize");
int tableSize = Hashing.closedTableSize(expectedSize, LOAD_FACTOR);
this.hashTableKToV = createTable(tableSize);
this.hashTableVToK = createTable(tableSize);
this.mask = tableSize - 1;
this.modCount = 0;
this.size = 0;
}
/**
* Finds and removes {@code entry} from the bucket linked lists in both the
* key-to-value direction and the value-to-key direction.
*/
private void delete(BiEntry<K, V> entry) {
int keyBucket = entry.keyHash & mask;
BiEntry<K, V> prevBucketEntry = null;
for (BiEntry<K, V> bucketEntry = hashTableKToV[keyBucket]; true; bucketEntry = bucketEntry.nextInKToVBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
hashTableKToV[keyBucket] = entry.nextInKToVBucket;
} else {
prevBucketEntry.nextInKToVBucket = entry.nextInKToVBucket;
}
break;
}
prevBucketEntry = bucketEntry;
}
int valueBucket = entry.valueHash & mask;
prevBucketEntry = null;
for (BiEntry<K, V> bucketEntry = hashTableVToK[valueBucket];; bucketEntry = bucketEntry.nextInVToKBucket) {
if (bucketEntry == entry) {
if (prevBucketEntry == null) {
hashTableVToK[valueBucket] = entry.nextInVToKBucket;
} else {
prevBucketEntry.nextInVToKBucket = entry.nextInVToKBucket;
}
break;
}
prevBucketEntry = bucketEntry;
}
size--;
modCount++;
}
private void insert(BiEntry<K, V> entry) {
int keyBucket = entry.keyHash & mask;
entry.nextInKToVBucket = hashTableKToV[keyBucket];
hashTableKToV[keyBucket] = entry;
int valueBucket = entry.valueHash & mask;
entry.nextInVToKBucket = hashTableVToK[valueBucket];
hashTableVToK[valueBucket] = entry;
size++;
modCount++;
}
private static int hash(@Nullable Object o) {
return Hashing.smear((o == null) ? 0 : o.hashCode());
}
private BiEntry<K, V> seekByKey(@Nullable Object key, int keyHash) {
for (BiEntry<K, V> entry = hashTableKToV[keyHash & mask]; entry != null; entry = entry.nextInKToVBucket) {
if (keyHash == entry.keyHash && Objects.equal(key, entry.key)) {
return entry;
}
}
return null;
}
private BiEntry<K, V> seekByValue(@Nullable Object value, int valueHash) {
for (BiEntry<K, V> entry = hashTableVToK[valueHash & mask]; entry != null; entry = entry.nextInVToKBucket) {
if (valueHash == entry.valueHash && Objects.equal(value, entry.value)) {
return entry;
}
}
return null;
}
@Override
public boolean containsKey(@Nullable Object key) {
return seekByKey(key, hash(key)) != null;
}
@Override
public boolean containsValue(@Nullable Object value) {
return seekByValue(value, hash(value)) != null;
}
@Nullable
@Override
public V get(@Nullable Object key) {
BiEntry<K, V> entry = seekByKey(key, hash(key));
return (entry == null) ? null : entry.value;
}
@Override
public V put(@Nullable K key, @Nullable V value) {
return put(key, value, false);
}
@Override
public V forcePut(@Nullable K key, @Nullable V value) {
return put(key, value, true);
}
private V put(@Nullable K key, @Nullable V value, boolean force) {
int keyHash = hash(key);
int valueHash = hash(value);
BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
if (oldEntryForKey != null && valueHash == oldEntryForKey.valueHash
&& Objects.equal(value, oldEntryForKey.value)) {
return value;
}
BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
if (oldEntryForValue != null) {
if (force) {
delete(oldEntryForValue);
} else {
throw new IllegalArgumentException("value already present: " + value);
}
}
if (oldEntryForKey != null) {
delete(oldEntryForKey);
}
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
insert(newEntry);
rehashIfNecessary();
return (oldEntryForKey == null) ? null : oldEntryForKey.value;
}
@Nullable
private K putInverse(@Nullable V value, @Nullable K key, boolean force) {
int valueHash = hash(value);
int keyHash = hash(key);
BiEntry<K, V> oldEntryForValue = seekByValue(value, valueHash);
if (oldEntryForValue != null && keyHash == oldEntryForValue.keyHash
&& Objects.equal(key, oldEntryForValue.key)) {
return key;
}
BiEntry<K, V> oldEntryForKey = seekByKey(key, keyHash);
if (oldEntryForKey != null) {
if (force) {
delete(oldEntryForKey);
} else {
throw new IllegalArgumentException("value already present: " + key);
}
}
if (oldEntryForValue != null) {
delete(oldEntryForValue);
}
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, value, valueHash);
insert(newEntry);
rehashIfNecessary();
return (oldEntryForValue == null) ? null : oldEntryForValue.key;
}
private void rehashIfNecessary() {
BiEntry<K, V>[] oldKToV = hashTableKToV;
if (Hashing.needsResizing(size, oldKToV.length, LOAD_FACTOR)) {
int newTableSize = oldKToV.length * 2;
this.hashTableKToV = createTable(newTableSize);
this.hashTableVToK = createTable(newTableSize);
this.mask = newTableSize - 1;
this.size = 0;
for (int bucket = 0; bucket < oldKToV.length; bucket++) {
BiEntry<K, V> entry = oldKToV[bucket];
while (entry != null) {
BiEntry<K, V> nextEntry = entry.nextInKToVBucket;
insert(entry);
entry = nextEntry;
}
}
this.modCount++;
}
}
@SuppressWarnings("unchecked")
private BiEntry<K, V>[] createTable(int length) {
return new BiEntry[length];
}
@Override
public V remove(@Nullable Object key) {
BiEntry<K, V> entry = seekByKey(key, hash(key));
if (entry == null) {
return null;
} else {
delete(entry);
return entry.value;
}
}
@Override
public void clear() {
size = 0;
Arrays.fill(hashTableKToV, null);
Arrays.fill(hashTableVToK, null);
modCount++;
}
@Override
public int size() {
return size;
}
abstract class Itr<T> implements Iterator<T> {
int nextBucket = 0;
BiEntry<K, V> next = null;
BiEntry<K, V> toRemove = null;
int expectedModCount = modCount;
private void checkForConcurrentModification() {
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
@Override
public boolean hasNext() {
checkForConcurrentModification();
if (next != null) {
return true;
}
while (nextBucket < hashTableKToV.length) {
if (hashTableKToV[nextBucket] != null) {
next = hashTableKToV[nextBucket++];
return true;
}
nextBucket++;
}
return false;
}
@Override
public T next() {
checkForConcurrentModification();
if (!hasNext()) {
throw new NoSuchElementException();
}
BiEntry<K, V> entry = next;
next = entry.nextInKToVBucket;
toRemove = entry;
return output(entry);
}
@Override
public void remove() {
checkForConcurrentModification();
checkRemove(toRemove != null);
delete(toRemove);
expectedModCount = modCount;
toRemove = null;
}
abstract T output(BiEntry<K, V> entry);
}
@Override
public Set<K> keySet() {
return new KeySet();
}
private final class KeySet extends Maps.KeySet<K, V> {
KeySet() {
super(HashBiMap.this);
}
@Override
public Iterator<K> iterator() {
return new Itr<K>() {
@Override
K output(BiEntry<K, V> entry) {
return entry.key;
}
};
}
@Override
public boolean remove(@Nullable Object o) {
BiEntry<K, V> entry = seekByKey(o, hash(o));
if (entry == null) {
return false;
} else {
delete(entry);
return true;
}
}
}
@Override
public Set<V> values() {
return inverse().keySet();
}
@Override
public Set<Entry<K, V>> entrySet() {
return new EntrySet();
}
private final class EntrySet extends Maps.EntrySet<K, V> {
@Override
Map<K, V> map() {
return HashBiMap.this;
}
@Override
public Iterator<Entry<K, V>> iterator() {
return new Itr<Entry<K, V>>() {
@Override
Entry<K, V> output(BiEntry<K, V> entry) {
return new MapEntry(entry);
}
class MapEntry extends AbstractMapEntry<K, V> {
BiEntry<K, V> delegate;
MapEntry(BiEntry<K, V> entry) {
this.delegate = entry;
}
@Override
public K getKey() {
return delegate.key;
}
@Override
public V getValue() {
return delegate.value;
}
@Override
public V setValue(V value) {
V oldValue = delegate.value;
int valueHash = hash(value);
if (valueHash == delegate.valueHash && Objects.equal(value, oldValue)) {
return value;
}
checkArgument(seekByValue(value, valueHash) == null, "value already present: %s", value);
delete(delegate);
BiEntry<K, V> newEntry = new BiEntry<K, V>(delegate.key, delegate.keyHash, value, valueHash);
insert(newEntry);
expectedModCount = modCount;
if (toRemove == delegate) {
toRemove = newEntry;
}
delegate = newEntry;
return oldValue;
}
}
};
}
}
private transient BiMap<V, K> inverse;
@Override
public BiMap<V, K> inverse() {
return (inverse == null) ? inverse = new Inverse() : inverse;
}
private final class Inverse extends AbstractMap<V, K> implements BiMap<V, K>, Serializable {
BiMap<K, V> forward() {
return HashBiMap.this;
}
@Override
public int size() {
return size;
}
@Override
public void clear() {
forward().clear();
}
@Override
public boolean containsKey(@Nullable Object value) {
return forward().containsValue(value);
}
@Override
public K get(@Nullable Object value) {
BiEntry<K, V> entry = seekByValue(value, hash(value));
return (entry == null) ? null : entry.key;
}
@Override
public K put(@Nullable V value, @Nullable K key) {
return putInverse(value, key, false);
}
@Override
public K forcePut(@Nullable V value, @Nullable K key) {
return putInverse(value, key, true);
}
@Override
public K remove(@Nullable Object value) {
BiEntry<K, V> entry = seekByValue(value, hash(value));
if (entry == null) {
return null;
} else {
delete(entry);
return entry.key;
}
}
@Override
public BiMap<K, V> inverse() {
return forward();
}
@Override
public Set<V> keySet() {
return new InverseKeySet();
}
private final class InverseKeySet extends Maps.KeySet<V, K> {
InverseKeySet() {
super(Inverse.this);
}
@Override
public boolean remove(@Nullable Object o) {
BiEntry<K, V> entry = seekByValue(o, hash(o));
if (entry == null) {
return false;
} else {
delete(entry);
return true;
}
}
@Override
public Iterator<V> iterator() {
return new Itr<V>() {
@Override
V output(BiEntry<K, V> entry) {
return entry.value;
}
};
}
}
@Override
public Set<K> values() {
return forward().keySet();
}
@Override
public Set<Entry<V, K>> entrySet() {
return new Maps.EntrySet<V, K>() {
@Override
Map<V, K> map() {
return Inverse.this;
}
@Override
public Iterator<Entry<V, K>> iterator() {
return new Itr<Entry<V, K>>() {
@Override
Entry<V, K> output(BiEntry<K, V> entry) {
return new InverseEntry(entry);
}
class InverseEntry extends AbstractMapEntry<V, K> {
BiEntry<K, V> delegate;
InverseEntry(BiEntry<K, V> entry) {
this.delegate = entry;
}
@Override
public V getKey() {
return delegate.value;
}
@Override
public K getValue() {
return delegate.key;
}
@Override
public K setValue(K key) {
K oldKey = delegate.key;
int keyHash = hash(key);
if (keyHash == delegate.keyHash && Objects.equal(key, oldKey)) {
return key;
}
checkArgument(seekByKey(key, keyHash) == null, "value already present: %s", key);
delete(delegate);
BiEntry<K, V> newEntry = new BiEntry<K, V>(key, keyHash, delegate.value,
delegate.valueHash);
insert(newEntry);
expectedModCount = modCount;
// This is safe because entries can only get bumped up to earlier in the
// iteration,
// so they can't get revisited.
return oldKey;
}
}
};
}
};
}
Object writeReplace() {
return new InverseSerializedForm<K, V>(HashBiMap.this);
}
}
private static final class InverseSerializedForm<K, V> implements Serializable {
private final HashBiMap<K, V> bimap;
InverseSerializedForm(HashBiMap<K, V> bimap) {
this.bimap = bimap;
}
Object readResolve() {
return bimap.inverse();
}
}
/**
* @serialData the number of entries, first key, first value, second key, second
* value, and so on.
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
Serialization.writeMap(this, stream);
}
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int size = Serialization.readCount(stream);
init(size);
Serialization.populateMap(this, stream, size);
}
@GwtIncompatible("Not needed in emulated source")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
/**
* Implementation of {@link Multimap} using hash tables.
*
* <p>
* The multimap does not store duplicate key-value pairs. Adding a new key-value
* pair equal to an existing key-value pair has no effect.
*
* <p>
* Keys and values may be null. All optional multimap methods are supported, and
* all returned views are modifiable.
*
* <p>
* This class is not threadsafe when any concurrent operations update the
* multimap. Concurrent read operations will work correctly. To allow concurrent
* update operations, wrap your multimap with a call to
* {@link Multimaps#synchronizedSetMultimap}.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultimap<K, V> extends AbstractSetMultimap<K, V> {
private static final int DEFAULT_VALUES_PER_KEY = 2;
@VisibleForTesting
transient int expectedValuesPerKey = DEFAULT_VALUES_PER_KEY;
/**
* Creates a new, empty {@code HashMultimap} with the default initial
* capacities.
*/
public static <K, V> HashMultimap<K, V> create() {
return new HashMultimap<K, V>();
}
/**
* Constructs an empty {@code HashMultimap} with enough capacity to hold the
* specified numbers of keys and values without rehashing.
*
* @param expectedKeys the expected number of distinct keys
* @param expectedValuesPerKey the expected average number of values per key
* @throws IllegalArgumentException if {@code expectedKeys} or {@code
* expectedValuesPerKey} is negative
*/
public static <K, V> HashMultimap<K, V> create(int expectedKeys, int expectedValuesPerKey) {
return new HashMultimap<K, V>(expectedKeys, expectedValuesPerKey);
}
/**
* Constructs a {@code HashMultimap} with the same mappings as the specified
* multimap. If a key-value mapping appears multiple times in the input
* multimap, it only appears once in the constructed multimap.
*
* @param multimap the multimap whose contents are copied to this multimap
*/
public static <K, V> HashMultimap<K, V> create(Multimap<? extends K, ? extends V> multimap) {
return new HashMultimap<K, V>(multimap);
}
private HashMultimap() {
super(new HashMap<K, Collection<V>>());
}
private HashMultimap(int expectedKeys, int expectedValuesPerKey) {
super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(expectedKeys));
Preconditions.checkArgument(expectedValuesPerKey >= 0);
this.expectedValuesPerKey = expectedValuesPerKey;
}
private HashMultimap(Multimap<? extends K, ? extends V> multimap) {
super(Maps.<K, Collection<V>>newHashMapWithExpectedSize(multimap.keySet().size()));
putAll(multimap);
}
/**
* {@inheritDoc}
*
* <p>
* Creates an empty {@code HashSet} for a collection of values for one key.
*
* @return a new {@code HashSet} containing a collection of values for one key
*/
@Override
Set<V> createCollection() {
return Sets.<V>newHashSetWithExpectedSize(expectedValuesPerKey);
}
/**
* @serialData expectedValuesPerKey, number of distinct keys, and then for each
* distinct key: the key, number of values for that key, and the
* key's values
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
stream.writeInt(expectedValuesPerKey);
Serialization.writeMultimap(this, stream);
}
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
expectedValuesPerKey = stream.readInt();
int distinctKeys = Serialization.readCount(stream);
Map<K, Collection<V>> map = Maps.newHashMapWithExpectedSize(distinctKeys);
setMap(map);
Serialization.populateMultimap(this, stream, distinctKeys);
}
@GwtIncompatible("Not needed in emulated source")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* Multiset implementation backed by a {@link HashMap}.
*
* @author Kevin Bourrillion
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(serializable = true, emulated = true)
public final class HashMultiset<E> extends AbstractMapBasedMultiset<E> {
/**
* Creates a new, empty {@code HashMultiset} using the default initial capacity.
*/
public static <E> HashMultiset<E> create() {
return new HashMultiset<E>();
}
/**
* Creates a new, empty {@code HashMultiset} with the specified expected number
* of distinct elements.
*
* @param distinctElements the expected number of distinct elements
* @throws IllegalArgumentException if {@code distinctElements} is negative
*/
public static <E> HashMultiset<E> create(int distinctElements) {
return new HashMultiset<E>(distinctElements);
}
/**
* Creates a new {@code HashMultiset} containing the specified elements.
*
* <p>
* This implementation is highly efficient when {@code elements} is itself a
* {@link Multiset}.
*
* @param elements the elements that the multiset should contain
*/
public static <E> HashMultiset<E> create(Iterable<? extends E> elements) {
HashMultiset<E> multiset = create(Multisets.inferDistinctElements(elements));
Iterables.addAll(multiset, elements);
return multiset;
}
private HashMultiset() {
super(new HashMap<E, Count>());
}
private HashMultiset(int distinctElements) {
super(Maps.<E, Count>newHashMapWithExpectedSize(distinctElements));
}
/**
* @serialData the number of distinct elements, the first element, its count,
* the second element, its count, and so on
*/
@GwtIncompatible("java.io.ObjectOutputStream")
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
Serialization.writeMultiset(this, stream);
}
@GwtIncompatible("java.io.ObjectInputStream")
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
int distinctElements = Serialization.readCount(stream);
setBackingMap(Maps.<E, Count>newHashMapWithExpectedSize(distinctElements));
Serialization.populateMultiset(this, stream, distinctElements);
}
@GwtIncompatible("Not needed in emulated source.")
private static final long serialVersionUID = 0;
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.primitives.Ints;
/**
* Static methods for implementing hash-based collections.
*
* @author Kevin Bourrillion
* @author Jesse Wilson
* @author Austin Appleby
*/
@GwtCompatible
final class Hashing {
private Hashing() {
}
private static final int C1 = 0xcc9e2d51;
private static final int C2 = 0x1b873593;
/*
* This method was rewritten in Java from an intermediate step of the Murmur
* hash function in
* http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp, which
* contained the following header:
*
* MurmurHash3 was written by Austin Appleby, and is placed in the public
* domain. The author hereby disclaims copyright to this source code.
*/
static int smear(int hashCode) {
return C2 * Integer.rotateLeft(hashCode * C1, 15);
}
static int smearedHash(@Nullable Object o) {
return smear((o == null) ? 0 : o.hashCode());
}
private static int MAX_TABLE_SIZE = Ints.MAX_POWER_OF_TWO;
static int closedTableSize(int expectedEntries, double loadFactor) {
// Get the recommended table size.
// Round down to the nearest power of 2.
expectedEntries = Math.max(expectedEntries, 2);
int tableSize = Integer.highestOneBit(expectedEntries);
// Check to make sure that we will not exceed the maximum load factor.
if (expectedEntries > (int) (loadFactor * tableSize)) {
tableSize <<= 1;
return (tableSize > 0) ? tableSize : MAX_TABLE_SIZE;
}
return tableSize;
}
static boolean needsResizing(int size, int tableSize, double loadFactor) {
return size > loadFactor * tableSize && tableSize < MAX_TABLE_SIZE;
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
/**
* List returned by {@link ImmutableCollection#asList} that delegates
* {@code contains} checks to the backing collection.
*
* @author Jared Levy
* @author Louis Wasserman
*/
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial")
abstract class ImmutableAsList<E> extends ImmutableList<E> {
abstract ImmutableCollection<E> delegateCollection();
@Override
public boolean contains(Object target) {
// The collection's contains() is at least as fast as ImmutableList's
// and is often faster.
return delegateCollection().contains(target);
}
@Override
public int size() {
return delegateCollection().size();
}
@Override
public boolean isEmpty() {
return delegateCollection().isEmpty();
}
@Override
boolean isPartialView() {
return delegateCollection().isPartialView();
}
/**
* Serialized form that leads to the same performance as the original list.
*/
@GwtIncompatible("serialization")
static class SerializedForm implements Serializable {
final ImmutableCollection<?> collection;
SerializedForm(ImmutableCollection<?> collection) {
this.collection = collection;
}
Object readResolve() {
return collection.asList();
}
private static final long serialVersionUID = 0;
}
@GwtIncompatible("serialization")
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Use SerializedForm");
}
@GwtIncompatible("serialization")
@Override
Object writeReplace() {
return new SerializedForm(delegateCollection());
}
}

View File

@ -0,0 +1,281 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import java.util.Map;
import com.google.common.annotations.GwtCompatible;
/**
* An immutable {@link BiMap} with reliable user-specified iteration order. Does
* not permit null keys or values. An {@code ImmutableBiMap} and its inverse
* have the same iteration ordering.
*
* <p>
* An instance of {@code ImmutableBiMap} contains its own data and will
* <i>never</i> change. {@code ImmutableBiMap} is convenient for
* {@code public static final} maps ("constant maps") and also lets you easily
* make a "defensive copy" of a bimap provided to your class by a caller.
*
* <p>
* <b>Note:</b> Although this class is not final, it cannot be subclassed as it
* has no public or protected constructors. Thus, instances of this class are
* guaranteed to be immutable.
*
* @author Jared Levy
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(serializable = true, emulated = true)
public abstract class ImmutableBiMap<K, V> extends ImmutableMap<K, V> implements BiMap<K, V> {
/**
* Returns the empty bimap.
*/
// Casting to any type is safe because the set will never hold any elements.
@SuppressWarnings("unchecked")
public static <K, V> ImmutableBiMap<K, V> of() {
return (ImmutableBiMap<K, V>) EmptyImmutableBiMap.INSTANCE;
}
/**
* Returns an immutable bimap containing a single entry.
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1) {
return new SingletonImmutableBiMap<K, V>(k1, v1);
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2) {
return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3) {
return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) {
return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4));
}
/**
* Returns an immutable map containing the given entries, in order.
*
* @throws IllegalArgumentException if duplicate keys or values are added
*/
public static <K, V> ImmutableBiMap<K, V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) {
return new RegularImmutableBiMap<K, V>(entryOf(k1, v1), entryOf(k2, v2), entryOf(k3, v3), entryOf(k4, v4),
entryOf(k5, v5));
}
// looking for of() with > 5 entries? Use the builder instead.
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static <K, V> Builder<K, V> builder() {
return new Builder<K, V>();
}
/**
* A builder for creating immutable bimap instances, especially {@code public
* static final} bimaps ("constant bimaps"). Example:
*
* <pre>
* {
* &#64;code
*
* static final ImmutableBiMap<String, Integer> WORD_TO_INT = new ImmutableBiMap.Builder<String, Integer>()
* .put("one", 1).put("two", 2).put("three", 3).build();
* }
* </pre>
*
* <p>
* For <i>small</i> immutable bimaps, the {@code ImmutableBiMap.of()} methods
* are even more convenient.
*
* <p>
* Builder instances can be reused - it is safe to call {@link #build} multiple
* times to build multiple bimaps in series. Each bimap is a superset of the
* bimaps created before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
public static final class Builder<K, V> extends ImmutableMap.Builder<K, V> {
/**
* Creates a new builder. The returned builder is equivalent to the builder
* generated by {@link ImmutableBiMap#builder}.
*/
public Builder() {
}
/**
* Associates {@code key} with {@code value} in the built bimap. Duplicate keys
* or values are not allowed, and will cause {@link #build} to fail.
*/
@Override
public Builder<K, V> put(K key, V value) {
super.put(key, value);
return this;
}
/**
* Associates all of the given map's keys and values in the built bimap.
* Duplicate keys or values are not allowed, and will cause {@link #build} to
* fail.
*
* @throws NullPointerException if any key or value in {@code map} is null
*/
@Override
public Builder<K, V> putAll(Map<? extends K, ? extends V> map) {
super.putAll(map);
return this;
}
/**
* Returns a newly-created immutable bimap.
*
* @throws IllegalArgumentException if duplicate keys or values were added
*/
@Override
public ImmutableBiMap<K, V> build() {
switch (size) {
case 0:
return of();
case 1:
return of(entries[0].getKey(), entries[0].getValue());
default:
return new RegularImmutableBiMap<K, V>(size, entries);
}
}
}
/**
* Returns an immutable bimap containing the same entries as {@code map}. If
* {@code map} somehow contains entries with duplicate keys (for example, if it
* is a {@code SortedMap} whose comparator is not <i>consistent with
* equals</i>), the results of this method are undefined.
*
* <p>
* Despite the method name, this method attempts to avoid actually copying the
* data when it is safe to do so. The exact circumstances under which a copy
* will or will not be performed are undocumented and subject to change.
*
* @throws IllegalArgumentException if two keys have the same value
* @throws NullPointerException if any key or value in {@code map} is null
*/
public static <K, V> ImmutableBiMap<K, V> copyOf(Map<? extends K, ? extends V> map) {
if (map instanceof ImmutableBiMap) {
@SuppressWarnings("unchecked") // safe since map is not writable
ImmutableBiMap<K, V> bimap = (ImmutableBiMap<K, V>) map;
// TODO(user): if we need to make a copy of a BiMap because the
// forward map is a view, don't make a copy of the non-view delegate map
if (!bimap.isPartialView()) {
return bimap;
}
}
Entry<?, ?>[] entries = map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
switch (entries.length) {
case 0:
return of();
case 1:
@SuppressWarnings("unchecked") // safe covariant cast in this context
Entry<K, V> entry = (Entry<K, V>) entries[0];
return of(entry.getKey(), entry.getValue());
default:
return new RegularImmutableBiMap<K, V>(entries);
}
}
private static final Entry<?, ?>[] EMPTY_ENTRY_ARRAY = new Entry<?, ?>[0];
ImmutableBiMap() {
}
/**
* {@inheritDoc}
*
* <p>
* The inverse of an {@code ImmutableBiMap} is another {@code ImmutableBiMap}.
*/
@Override
public abstract ImmutableBiMap<V, K> inverse();
/**
* Returns an immutable set of the values in this map. The values are in the
* same order as the parameters used to build this map.
*/
@Override
public ImmutableSet<V> values() {
return inverse().keySet();
}
/**
* Guaranteed to throw an exception and leave the bimap unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public V forcePut(K key, V value) {
throw new UnsupportedOperationException();
}
/**
* Serialized type for all ImmutableBiMap instances. It captures the logical
* contents and they are reconstructed using public factory methods. This
* ensures that the implementation types remain as implementation details.
*
* Since the bimap is immutable, ImmutableBiMap doesn't require special logic
* for keeping the bimap and its inverse in sync during serialization, the way
* AbstractBiMap does.
*/
private static class SerializedForm extends ImmutableMap.SerializedForm {
SerializedForm(ImmutableBiMap<?, ?> bimap) {
super(bimap);
}
@Override
Object readResolve() {
Builder<Object, Object> builder = new Builder<Object, Object>();
return createMap(builder);
}
private static final long serialVersionUID = 0;
}
@Override
Object writeReplace() {
return new SerializedForm(this);
}
}

View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2009 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.Serializable;
import java.util.Map;
import javax.annotation.Nullable;
import com.google.common.primitives.Primitives;
/**
* A class-to-instance map backed by an {@link ImmutableMap}. See also
* {@link MutableClassToInstanceMap}.
*
* @author Kevin Bourrillion
* @since 2.0 (imported from Google Collections Library)
*/
public final class ImmutableClassToInstanceMap<B> extends ForwardingMap<Class<? extends B>, B>
implements ClassToInstanceMap<B>, Serializable {
/**
* Returns a new builder. The generated builder is equivalent to the builder
* created by the {@link Builder} constructor.
*/
public static <B> Builder<B> builder() {
return new Builder<B>();
}
/**
* A builder for creating immutable class-to-instance maps. Example:
*
* <pre>
* {
* &#64;code
*
* static final ImmutableClassToInstanceMap<Handler> HANDLERS = new ImmutableClassToInstanceMap.Builder<Handler>()
* .put(FooHandler.class, new FooHandler()).put(BarHandler.class, new SubBarHandler())
* .put(Handler.class, new QuuxHandler()).build();
* }
* </pre>
*
* <p>
* After invoking {@link #build()} it is still possible to add more entries and
* build again. Thus each map generated by this builder will be a superset of
* any map generated before it.
*
* @since 2.0 (imported from Google Collections Library)
*/
public static final class Builder<B> {
private final ImmutableMap.Builder<Class<? extends B>, B> mapBuilder = ImmutableMap.builder();
/**
* Associates {@code key} with {@code value} in the built map. Duplicate keys
* are not allowed, and will cause {@link #build} to fail.
*/
public <T extends B> Builder<B> put(Class<T> key, T value) {
mapBuilder.put(key, value);
return this;
}
/**
* Associates all of {@code map's} keys and values in the built map. Duplicate
* keys are not allowed, and will cause {@link #build} to fail.
*
* @throws NullPointerException if any key or value in {@code map} is null
* @throws ClassCastException if any value is not an instance of the type
* specified by its key
*/
public <T extends B> Builder<B> putAll(Map<? extends Class<? extends T>, ? extends T> map) {
for (Entry<? extends Class<? extends T>, ? extends T> entry : map.entrySet()) {
Class<? extends T> type = entry.getKey();
T value = entry.getValue();
mapBuilder.put(type, cast(type, value));
}
return this;
}
private static <B, T extends B> T cast(Class<T> type, B value) {
return Primitives.wrap(type).cast(value);
}
/**
* Returns a new immutable class-to-instance map containing the entries provided
* to this builder.
*
* @throws IllegalArgumentException if duplicate keys were added
*/
public ImmutableClassToInstanceMap<B> build() {
return new ImmutableClassToInstanceMap<B>(mapBuilder.build());
}
}
/**
* Returns an immutable map containing the same entries as {@code map}. If
* {@code map} somehow contains entries with duplicate keys (for example, if it
* is a {@code SortedMap} whose comparator is not <i>consistent with
* equals</i>), the results of this method are undefined.
*
* <p>
* <b>Note:</b> Despite what the method name suggests, if {@code map} is an
* {@code ImmutableClassToInstanceMap}, no copy will actually be performed.
*
* @throws NullPointerException if any key or value in {@code map} is null
* @throws ClassCastException if any value is not an instance of the type
* specified by its key
*/
public static <B, S extends B> ImmutableClassToInstanceMap<B> copyOf(
Map<? extends Class<? extends S>, ? extends S> map) {
if (map instanceof ImmutableClassToInstanceMap) {
@SuppressWarnings("unchecked") // covariant casts safe (unmodifiable)
// Eclipse won't compile if we cast to the parameterized type.
ImmutableClassToInstanceMap<B> cast = (ImmutableClassToInstanceMap) map;
return cast;
}
return new Builder<B>().putAll(map).build();
}
private final ImmutableMap<Class<? extends B>, B> delegate;
private ImmutableClassToInstanceMap(ImmutableMap<Class<? extends B>, B> delegate) {
this.delegate = delegate;
}
@Override
protected Map<Class<? extends B>, B> delegate() {
return delegate;
}
@Override
@SuppressWarnings("unchecked") // value could not get in if not a T
@Nullable
public <T extends B> T getInstance(Class<T> type) {
return (T) delegate.get(checkNotNull(type));
}
/**
* Guaranteed to throw an exception and leave the map unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public <T extends B> T putInstance(Class<T> type, T value) {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,373 @@
/*
* Copyright (C) 2008 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.CollectPreconditions.checkNonnegative;
import static com.google.common.collect.ObjectArrays.checkElementsNotNull;
import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Iterator;
import javax.annotation.Nullable;
import com.google.common.annotations.GwtCompatible;
/**
* An immutable collection. Does not permit null elements.
*
* <p>
* In addition to the {@link Collection} methods, this class has an
* {@link #asList()} method, which returns a list view of the collection's
* elements.
*
* <p>
* <b>Note:</b> Although this class is not final, it cannot be subclassed
* outside of this package as it has no public or protected constructors. Thus,
* instances of this type are guaranteed to be immutable.
*
* @author Jesse Wilson
* @since 2.0 (imported from Google Collections Library)
*/
@GwtCompatible(emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
public abstract class ImmutableCollection<E> extends AbstractCollection<E> implements Serializable {
ImmutableCollection() {
}
/**
* Returns an unmodifiable iterator across the elements in this collection.
*/
@Override
public abstract UnmodifiableIterator<E> iterator();
@Override
public final Object[] toArray() {
int size = size();
if (size == 0) {
return ObjectArrays.EMPTY_ARRAY;
}
Object[] result = new Object[size()];
copyIntoArray(result, 0);
return result;
}
@Override
public final <T> T[] toArray(T[] other) {
checkNotNull(other);
int size = size();
if (other.length < size) {
other = ObjectArrays.newArray(other, size);
} else if (other.length > size) {
other[size] = null;
}
copyIntoArray(other, 0);
return other;
}
@Override
public boolean contains(@Nullable Object object) {
return object != null && super.contains(object);
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean add(E e) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean remove(Object object) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean addAll(Collection<? extends E> newElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean removeAll(Collection<?> oldElements) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final boolean retainAll(Collection<?> elementsToKeep) {
throw new UnsupportedOperationException();
}
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@Deprecated
@Override
public final void clear() {
throw new UnsupportedOperationException();
}
/*
* TODO(kevinb): Restructure code so ImmutableList doesn't contain this
* variable, which it doesn't use.
*/
private transient ImmutableList<E> asList;
/**
* Returns a list view of the collection.
*
* @since 2.0
*/
public ImmutableList<E> asList() {
ImmutableList<E> list = asList;
return (list == null) ? (asList = createAsList()) : list;
}
ImmutableList<E> createAsList() {
switch (size()) {
case 0:
return ImmutableList.of();
case 1:
return ImmutableList.of(iterator().next());
default:
return new RegularImmutableAsList<E>(this, toArray());
}
}
/**
* Returns {@code true} if this immutable collection's implementation contains
* references to user-created objects that aren't accessible via this
* collection's methods. This is generally used to determine whether
* {@code copyOf} implementations should make an explicit copy to avoid memory
* leaks.
*/
abstract boolean isPartialView();
/**
* Copies the contents of this immutable collection into the specified array at
* the specified offset. Returns {@code offset + size()}.
*/
int copyIntoArray(Object[] dst, int offset) {
for (E e : this) {
dst[offset++] = e;
}
return offset;
}
Object writeReplace() {
// We serialize by default to ImmutableList, the simplest thing that works.
return new ImmutableList.SerializedForm(toArray());
}
/**
* Abstract base class for builders of {@link ImmutableCollection} types.
*
* @since 10.0
*/
public abstract static class Builder<E> {
static final int DEFAULT_INITIAL_CAPACITY = 4;
static int expandedCapacity(int oldCapacity, int minCapacity) {
if (minCapacity < 0) {
throw new AssertionError("cannot store more than MAX_VALUE elements");
}
// careful of overflow!
int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;
if (newCapacity < minCapacity) {
newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;
}
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
// guaranteed to be >= newCapacity
}
return newCapacity;
}
Builder() {
}
/**
* Adds {@code element} to the {@code ImmutableCollection} being built.
*
* <p>
* Note that each builder class covariantly returns its own type from this
* method.
*
* @param element the element to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code element} is null
*/
public abstract Builder<E> add(E element);
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>
* Note that each builder class overrides this method in order to covariantly
* return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a null
* element
*/
public Builder<E> add(E... elements) {
for (E element : elements) {
add(element);
}
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>
* Note that each builder class overrides this method in order to covariantly
* return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a null
* element
*/
public Builder<E> addAll(Iterable<? extends E> elements) {
for (E element : elements) {
add(element);
}
return this;
}
/**
* Adds each element of {@code elements} to the {@code ImmutableCollection}
* being built.
*
* <p>
* Note that each builder class overrides this method in order to covariantly
* return its own type.
*
* @param elements the elements to add
* @return this {@code Builder} instance
* @throws NullPointerException if {@code elements} is null or contains a null
* element
*/
public Builder<E> addAll(Iterator<? extends E> elements) {
while (elements.hasNext()) {
add(elements.next());
}
return this;
}
/**
* Returns a newly-created {@code ImmutableCollection} of the appropriate type,
* containing the elements provided to this builder.
*
* <p>
* Note that each builder class covariantly returns the appropriate type of
* {@code ImmutableCollection} from this method.
*/
public abstract ImmutableCollection<E> build();
}
abstract static class ArrayBasedBuilder<E> extends ImmutableCollection.Builder<E> {
Object[] contents;
int size;
ArrayBasedBuilder(int initialCapacity) {
checkNonnegative(initialCapacity, "initialCapacity");
this.contents = new Object[initialCapacity];
this.size = 0;
}
/**
* Expand the absolute capacity of the builder so it can accept at least the
* specified number of elements without being resized.
*/
private void ensureCapacity(int minCapacity) {
if (contents.length < minCapacity) {
this.contents = ObjectArrays.arraysCopyOf(this.contents,
expandedCapacity(contents.length, minCapacity));
}
}
@Override
public ArrayBasedBuilder<E> add(E element) {
checkNotNull(element);
ensureCapacity(size + 1);
contents[size++] = element;
return this;
}
@Override
public Builder<E> add(E... elements) {
checkElementsNotNull(elements);
ensureCapacity(size + elements.length);
System.arraycopy(elements, 0, contents, size, elements.length);
size += elements.length;
return this;
}
@Override
public Builder<E> addAll(Iterable<? extends E> elements) {
if (elements instanceof Collection) {
Collection<?> collection = (Collection<?>) elements;
ensureCapacity(size + collection.size());
}
super.addAll(elements);
return this;
}
}
}

Some files were not shown because too many files have changed in this diff Show More