Skip to content

Commit

Permalink
Add ConcurrentHashMultiset.create(ConcurrentMap).
Browse files Browse the repository at this point in the history
Deprecated and 'MOE insert public' for ConcurrentHashMultiset.create(MapMaker).
Migrate [] users to the latter.

RELNOTES: None
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=126901404
  • Loading branch information
kluever authored and cpovirk committed Jul 8, 2016
1 parent 6427916 commit 7850a14
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 35 deletions.
Expand Up @@ -369,12 +369,10 @@ public void testIdentityKeyEquality_weakKeys() {
private void testIdentityKeyEquality(
MapMakerInternalMap.Strength keyStrength) {

MapMaker mapMaker = new MapMaker()
.setKeyStrength(keyStrength)
.keyEquivalence(Equivalence.identity());
ConcurrentMap<String, AtomicInteger> map =
new MapMaker().setKeyStrength(keyStrength).keyEquivalence(Equivalence.identity()).makeMap();

ConcurrentHashMultiset<String> multiset =
ConcurrentHashMultiset.create(mapMaker);
ConcurrentHashMultiset<String> multiset = ConcurrentHashMultiset.create(map);

String s1 = new String("a");
String s2 = new String("a");
Expand Down Expand Up @@ -408,12 +406,10 @@ public void testLogicalKeyEquality_weakKeys() {
private void testLogicalKeyEquality(
MapMakerInternalMap.Strength keyStrength) {

MapMaker mapMaker = new MapMaker()
.setKeyStrength(keyStrength)
.keyEquivalence(Equivalence.equals());
ConcurrentMap<String, AtomicInteger> map =
new MapMaker().setKeyStrength(keyStrength).keyEquivalence(Equivalence.equals()).makeMap();

ConcurrentHashMultiset<String> multiset =
ConcurrentHashMultiset.create(mapMaker);
ConcurrentHashMultiset<String> multiset = ConcurrentHashMultiset.create(map);

String s1 = new String("a");
String s2 = new String("a");
Expand All @@ -435,31 +431,30 @@ private void testLogicalKeyEquality(
}

public void testSerializationWithMapMaker1() {
MapMaker mapMaker = new MapMaker();
multiset = ConcurrentHashMultiset.create(mapMaker);
ConcurrentMap<String, AtomicInteger> map = new MapMaker().makeMap();
multiset = ConcurrentHashMultiset.create(map);
reserializeAndAssert(multiset);
}

public void testSerializationWithMapMaker2() {
MapMaker mapMaker = new MapMaker();
multiset = ConcurrentHashMultiset.create(mapMaker);
ConcurrentMap<String, AtomicInteger> map = new MapMaker().makeMap();
multiset = ConcurrentHashMultiset.create(map);
multiset.addAll(ImmutableList.of("a", "a", "b", "c", "d", "b"));
reserializeAndAssert(multiset);
}

public void testSerializationWithMapMaker3() {
MapMaker mapMaker = new MapMaker();
multiset = ConcurrentHashMultiset.create(mapMaker);
ConcurrentMap<String, AtomicInteger> map = new MapMaker().makeMap();
multiset = ConcurrentHashMultiset.create(map);
multiset.addAll(ImmutableList.of("a", "a", "b", "c", "d", "b"));
reserializeAndAssert(multiset);
}

public void testSerializationWithMapMaker_preservesIdentityKeyEquivalence() {
MapMaker mapMaker = new MapMaker()
.keyEquivalence(Equivalence.identity());
ConcurrentMap<String, AtomicInteger> map =
new MapMaker().keyEquivalence(Equivalence.identity()).makeMap();

ConcurrentHashMultiset<String> multiset =
ConcurrentHashMultiset.create(mapMaker);
ConcurrentHashMultiset<String> multiset = ConcurrentHashMultiset.create(map);
multiset = reserializeAndAssert(multiset);

String s1 = new String("a");
Expand Down
42 changes: 27 additions & 15 deletions guava/src/com/google/common/collect/ConcurrentHashMultiset.java
Expand Up @@ -106,44 +106,56 @@ public static <E> ConcurrentHashMultiset<E> create(Iterable<? extends E> element
}

/**
* Creates a new, empty {@code ConcurrentHashMultiset} using {@code mapMaker}
* to construct the internal backing map.
* Creates a new, empty {@code ConcurrentHashMultiset} using {@code mapMaker} to construct the
* internal backing map.
*
* <p>If this {@link MapMaker} is configured to use entry eviction of any kind, this eviction
* applies to all occurrences of a given element as a single unit. However, most updates to the
* multiset do not count as map updates at all, since we're usually just mutating the value
* stored in the map, so {@link MapMaker#expireAfterAccess} makes sense (evict the entry that
* was queried or updated longest ago), but {@link MapMaker#expireAfterWrite} doesn't, because
* the eviction time is measured from when we saw the first occurrence of the object.
* multiset do not count as map updates at all, since we're usually just mutating the value stored
* in the map, so {@link MapMaker#expireAfterAccess} makes sense (evict the entry that was queried
* or updated longest ago), but {@link MapMaker#expireAfterWrite} doesn't, because the eviction
* time is measured from when we saw the first occurrence of the object.
*
* <p>The returned multiset is serializable but any serialization caveats
* given in {@code MapMaker} apply.
* <p>The returned multiset is serializable but any serialization caveats given in {@code
* MapMaker} apply.
*
* <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 15.0 (source compatible (accepting the since removed {@code GenericMapMaker} class)
* since 7.0)
* @deprecated Use {@link #create(ConcurrentMap)} instead. This method is scheduled for deletion
* in October 2016.
*/
@Beta
@Deprecated
public static <E> ConcurrentHashMultiset<E> create(MapMaker mapMaker) {
return new ConcurrentHashMultiset<E>(mapMaker.<E, AtomicInteger>makeMap());
return create(mapMaker.<E, AtomicInteger>makeMap());
}

/**
* Creates an instance using {@code countMap} to store elements and their counts.
* Creates a new, empty {@code ConcurrentHashMultiset} using {@code countMap} as the internal
* backing map.
*
* <p>This instance will assume ownership of {@code countMap}, and other code
* should not maintain references to the map or modify it in any way.
* <p>This instance will assume ownership of {@code countMap}, and other code should not maintain
* references to the map or modify it in any way.
*
* @param countMap backing map for storing the elements in the multiset and
* their counts. It must be empty.
* <p>The returned multiset is serializable if the input map is.
*
* @param countMap backing map for storing the elements in the multiset and their counts. It must
* be empty.
* @throws IllegalArgumentException if {@code countMap} is not empty
* @since 20.0
*/
@Beta
public static <E> ConcurrentHashMultiset<E> create(ConcurrentMap<E, AtomicInteger> countMap) {
return new ConcurrentHashMultiset<E>(countMap);
}

@VisibleForTesting
ConcurrentHashMultiset(ConcurrentMap<E, AtomicInteger> countMap) {
checkArgument(countMap.isEmpty());
checkArgument(countMap.isEmpty(), "the backing map (%s) must be empty", countMap);
this.countMap = countMap;
}

Expand Down

0 comments on commit 7850a14

Please sign in to comment.