diff options
Diffstat (limited to 'guava/src/com/google/common/collect/ConcurrentHashMultiset.java')
-rw-r--r-- | guava/src/com/google/common/collect/ConcurrentHashMultiset.java | 85 |
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; + } } /** |