Skip to content

Commit

Permalink
Improve allocation behavior of Multiset copying and addAll implementa…
Browse files Browse the repository at this point in the history
…tions in both Guava versions.

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=182573989
  • Loading branch information
lowasser authored and cpovirk committed Jan 19, 2018
1 parent c046982 commit 5b39c8b
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 17 deletions.
Expand Up @@ -17,6 +17,7 @@
package com.google.common.collect; package com.google.common.collect;


import static com.google.common.base.Preconditions.checkArgument; 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.checkNonnegative;


import com.google.common.annotations.GwtCompatible; import com.google.common.annotations.GwtCompatible;
Expand Down Expand Up @@ -220,6 +221,14 @@ Entry<E> result(int entryIndex) {
}; };
} }


/** Allocation-free implementation of {@code target.addAll(this)}. */
void addTo(Multiset<? super E> target) {
checkNotNull(target);
for (int i = backingMap.firstIndex(); i >= 0; i = backingMap.nextIndex(i)) {
target.add(backingMap.getKey(i), backingMap.getValue(i));
}
}

@Override @Override
final int distinctElements() { final int distinctElements() {
return backingMap.size(); return backingMap.size();
Expand Down
38 changes: 32 additions & 6 deletions android/guava/src/com/google/common/collect/Multisets.java
Expand Up @@ -857,17 +857,43 @@ static boolean equalsImpl(Multiset<?> multiset, @NullableDecl Object object) {


/** An implementation of {@link Multiset#addAll}. */ /** An implementation of {@link Multiset#addAll}. */
static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) { static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) {
if (elements.isEmpty()) { checkNotNull(self);
checkNotNull(elements);
if (elements instanceof Multiset) {
return addAllImpl(self, cast(elements));
} else if (elements.isEmpty()) {
return false; return false;
} else {
return Iterators.addAll(self, elements.iterator());
} }
if (elements instanceof Multiset) { }
Multiset<? extends E> that = cast(elements);
for (Entry<? extends E> entry : that.entrySet()) { /** A specialization of {@code addAllImpl} for when {@code elements} is itself a Multiset. */
private static <E> boolean addAllImpl(Multiset<E> self, Multiset<? extends E> elements) {
// It'd be nice if we could specialize for ImmutableMultiset here without also retaining
// its code when it's not in scope...
if (elements instanceof AbstractMapBasedMultiset) {
return addAllImpl(self, (AbstractMapBasedMultiset<? extends E>) elements);
} else if (elements.isEmpty()) {
return false;
} else {
for (Multiset.Entry<? extends E> entry : elements.entrySet()) {
self.add(entry.getElement(), entry.getCount()); self.add(entry.getElement(), entry.getCount());
} }
} else { return true;
Iterators.addAll(self, elements.iterator()); }
}

/**
* A specialization of {@code addAllImpl} for when {@code elements} is an
* AbstractMapBasedMultiset.
*/
private static <E> boolean addAllImpl(
Multiset<E> self, AbstractMapBasedMultiset<? extends E> elements) {
if (elements.isEmpty()) {
return false;
} }
elements.addTo(self);
return true; return true;
} }


Expand Down
4 changes: 1 addition & 3 deletions guava/src/com/google/common/collect/ImmutableMultiset.java
Expand Up @@ -541,9 +541,7 @@ public Builder<E> add(E... elements) {
public Builder<E> addAll(Iterable<? extends E> elements) { public Builder<E> addAll(Iterable<? extends E> elements) {
if (elements instanceof Multiset) { if (elements instanceof Multiset) {
Multiset<? extends E> multiset = Multisets.cast(elements); Multiset<? extends E> multiset = Multisets.cast(elements);
for (Entry<? extends E> entry : multiset.entrySet()) { multiset.forEachEntry((e, n) -> contents.add(checkNotNull(e), n));
addCopies(entry.getElement(), entry.getCount());
}
} else { } else {
super.addAll(elements); super.addAll(elements);
} }
Expand Down
22 changes: 14 additions & 8 deletions guava/src/com/google/common/collect/Multisets.java
Expand Up @@ -889,17 +889,23 @@ static boolean equalsImpl(Multiset<?> multiset, @NullableDecl Object object) {


/** An implementation of {@link Multiset#addAll}. */ /** An implementation of {@link Multiset#addAll}. */
static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) { static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) {
if (elements.isEmpty()) { checkNotNull(self);
return false; checkNotNull(elements);
}
if (elements instanceof Multiset) { if (elements instanceof Multiset) {
Multiset<? extends E> that = cast(elements); return addAllImpl(self, cast(elements));
for (Entry<? extends E> entry : that.entrySet()) { } else if (elements.isEmpty()) {
self.add(entry.getElement(), entry.getCount()); return false;
}
} else { } else {
Iterators.addAll(self, elements.iterator()); return Iterators.addAll(self, elements.iterator());
}
}

/** A specialization of {@code addAllImpl} for when {@code elements} is itself a Multiset. */
private static <E> boolean addAllImpl(Multiset<E> self, Multiset<? extends E> elements) {
if (elements.isEmpty()) {
return false;
} }
elements.forEachEntry(self::add);
return true; return true;
} }


Expand Down

0 comments on commit 5b39c8b

Please sign in to comment.