aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/ConcurrentHashMultiset.java')
-rw-r--r--guava/src/com/google/common/collect/ConcurrentHashMultiset.java85
1 files changed, 44 insertions, 41 deletions
diff --git a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
index 1a1331b..46b8d6e 100644
--- a/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
+++ b/guava/src/com/google/common/collect/ConcurrentHashMultiset.java
@@ -17,7 +17,6 @@
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.Preconditions.checkState;
import static com.google.common.collect.Multisets.checkNonnegative;
@@ -31,7 +30,6 @@ 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.List;
import java.util.Map;
@@ -46,10 +44,6 @@ import javax.annotation.Nullable;
* A multiset that supports concurrent modifications and that provides atomic versions of most
* {@code Multiset} operations (exceptions where noted). Null elements are not supported.
*
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset">
- * {@code Multiset}</a>.
- *
* @author Cliff L. Biffle
* @author mike nonemacher
* @since 2.0 (imported from Google Collections Library)
@@ -118,7 +112,7 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* <p>Finally, soft/weak values can be used but are not very useful: the values are created
* internally and not exposed externally, so no one else will have a strong reference to the
* values. Weak keys on the other hand can be useful in some scenarios.
- *
+ *
* @since 7.0
*/
@Beta
@@ -151,11 +145,26 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @return the nonnegative number of occurrences of the element
*/
@Override public int count(@Nullable Object element) {
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
return (existingCounter == null) ? 0 : existingCounter.get();
}
/**
+ * Depending on the type of the underlying map, map.get may throw NullPointerException or
+ * ClassCastException, if the object is null or of the wrong type. We usually just want to treat
+ * those cases as if the element isn't in the map, by catching the exceptions and returning null.
+ */
+ private AtomicInteger safeGet(Object element) {
+ try {
+ return countMap.get(element);
+ } catch (NullPointerException e) {
+ return null;
+ } catch (ClassCastException e) {
+ return null;
+ }
+ }
+
+ /**
* {@inheritDoc}
*
* <p>If the data in the multiset is modified by any other threads during this method,
@@ -209,14 +218,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* the resulting amount would exceed {@link Integer#MAX_VALUE}
*/
@Override public int add(E element, int occurrences) {
- checkNotNull(element);
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
while (true) {
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
if (existingCounter == null) {
existingCounter = countMap.putIfAbsent(element, new AtomicInteger(occurrences));
if (existingCounter == null) {
@@ -264,22 +272,13 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @return the count of the element before the operation; possibly zero
* @throws IllegalArgumentException if {@code occurrences} is negative
*/
- /*
- * TODO(cpovirk): remove and removeExactly currently accept null inputs only
- * if occurrences == 0. This satisfies both NullPointerTester and
- * CollectionRemoveTester.testRemove_nullAllowed, but it's not clear that it's
- * a good policy, especially because, in order for the test to pass, the
- * parameter must be misleadingly annotated as @Nullable. I suspect that
- * we'll want to remove @Nullable, add an eager checkNotNull, and loosen up
- * testRemove_nullAllowed.
- */
@Override public int remove(@Nullable Object element, int occurrences) {
if (occurrences == 0) {
return count(element);
}
checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
if (existingCounter == null) {
return 0;
}
@@ -318,7 +317,7 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
}
checkArgument(occurrences > 0, "Invalid occurrences: %s", occurrences);
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
if (existingCounter == null) {
return false;
}
@@ -347,10 +346,9 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @throws IllegalArgumentException if {@code count} is negative
*/
@Override public int setCount(E element, int count) {
- checkNotNull(element);
checkNonnegative(count, "count");
while (true) {
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
if (existingCounter == null) {
if (count == 0) {
return 0;
@@ -402,11 +400,10 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
* @throws IllegalArgumentException if {@code expectedOldCount} or {@code newCount} is negative
*/
@Override public boolean setCount(E element, int expectedOldCount, int newCount) {
- checkNotNull(element);
checkNonnegative(expectedOldCount, "oldCount");
checkNonnegative(newCount, "newCount");
- AtomicInteger existingCounter = Maps.safeGet(countMap, element);
+ AtomicInteger existingCounter = safeGet(element);
if (existingCounter == null) {
if (expectedOldCount != 0) {
return false;
@@ -451,23 +448,14 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
@Override protected Set<E> delegate() {
return delegate;
}
-
- @Override
- public boolean contains(@Nullable Object object) {
- return object != null && Collections2.safeContains(delegate, object);
- }
-
- @Override
- public boolean containsAll(Collection<?> collection) {
- return standardContainsAll(collection);
- }
-
@Override public boolean remove(Object object) {
- return object != null && Collections2.safeRemove(delegate, object);
- }
-
- @Override public boolean removeAll(Collection<?> c) {
- return standardRemoveAll(c);
+ try {
+ return delegate.remove(object);
+ } catch (NullPointerException e) {
+ return false;
+ } catch (ClassCastException e) {
+ return false;
+ }
}
};
}
@@ -559,6 +547,21 @@ public final class ConcurrentHashMultiset<E> extends AbstractMultiset<E> impleme
Iterators.addAll(list, iterator());
return list;
}
+
+ @Override public boolean remove(Object object) {
+ if (object instanceof Multiset.Entry) {
+ Multiset.Entry<?> entry = (Multiset.Entry<?>) object;
+ Object element = entry.getElement();
+ int entryCount = entry.getCount();
+ if (entryCount != 0) {
+ // Safe as long as we never add a new entry, which we won't.
+ @SuppressWarnings("unchecked")
+ Multiset<Object> multiset = (Multiset) multiset();
+ return multiset.setCount(element, entryCount, 0);
+ }
+ }
+ return false;
+ }
}
/**