aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java')
-rw-r--r--guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java205
1 files changed, 129 insertions, 76 deletions
diff --git a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
index 3db3405..7318d9b 100644
--- a/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
+++ b/guava/src/com/google/common/collect/RegularImmutableSortedMultiset.java
@@ -15,11 +15,16 @@
package com.google.common.collect;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkPositionIndexes;
-import static com.google.common.collect.BoundType.CLOSED;
+import static com.google.common.collect.SortedLists.KeyAbsentBehavior.INVERTED_INSERTION_INDEX;
+import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_HIGHER;
+import static com.google.common.collect.SortedLists.KeyAbsentBehavior.NEXT_LOWER;
+import static com.google.common.collect.SortedLists.KeyPresentBehavior.ANY_PRESENT;
import com.google.common.primitives.Ints;
+import java.util.Comparator;
+import java.util.List;
+
import javax.annotation.Nullable;
/**
@@ -27,119 +32,167 @@ import javax.annotation.Nullable;
*
* @author Louis Wasserman
*/
-@SuppressWarnings("serial") // uses writeReplace, not default serialization
final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> {
- private final transient RegularImmutableSortedSet<E> elementSet;
- private final transient int[] counts;
- private final transient long[] cumulativeCounts;
- private final transient int offset;
- private final transient int length;
+ private static final class CumulativeCountEntry<E> extends Multisets.AbstractEntry<E> {
+ final E element;
+ final int count;
+ final long cumulativeCount;
+
+ CumulativeCountEntry(E element, int count, @Nullable CumulativeCountEntry<E> previous) {
+ this.element = element;
+ this.count = count;
+ this.cumulativeCount = count + ((previous == null) ? 0 : previous.cumulativeCount);
+ }
+
+ @Override
+ public E getElement() {
+ return element;
+ }
+
+ @Override
+ public int getCount() {
+ return count;
+ }
+ }
+
+ static <E> RegularImmutableSortedMultiset<E> createFromSorted(Comparator<? super E> comparator,
+ List<? extends Multiset.Entry<E>> entries) {
+ List<CumulativeCountEntry<E>> newEntries = Lists.newArrayListWithCapacity(entries.size());
+ CumulativeCountEntry<E> previous = null;
+ for (Multiset.Entry<E> entry : entries) {
+ newEntries.add(
+ previous = new CumulativeCountEntry<E>(entry.getElement(), entry.getCount(), previous));
+ }
+ return new RegularImmutableSortedMultiset<E>(comparator, ImmutableList.copyOf(newEntries));
+ }
+
+ final transient ImmutableList<CumulativeCountEntry<E>> entries;
RegularImmutableSortedMultiset(
- RegularImmutableSortedSet<E> elementSet,
- int[] counts,
- long[] cumulativeCounts,
- int offset,
- int length) {
- this.elementSet = elementSet;
- this.counts = counts;
- this.cumulativeCounts = cumulativeCounts;
- this.offset = offset;
- this.length = length;
+ Comparator<? super E> comparator, ImmutableList<CumulativeCountEntry<E>> entries) {
+ super(comparator);
+ this.entries = entries;
+ assert !entries.isEmpty();
}
- private Entry<E> getEntry(int index) {
- return Multisets.immutableEntry(
- elementSet.asList().get(index),
- counts[offset + index]);
+ ImmutableList<E> elementList() {
+ return new TransformedImmutableList<CumulativeCountEntry<E>, E>(entries) {
+ @Override
+ E transform(CumulativeCountEntry<E> entry) {
+ return entry.getElement();
+ }
+ };
}
@Override
- public Entry<E> firstEntry() {
- return getEntry(0);
+ ImmutableSortedSet<E> createElementSet() {
+ return new RegularImmutableSortedSet<E>(elementList(), comparator());
}
@Override
- public Entry<E> lastEntry() {
- return getEntry(length - 1);
+ ImmutableSortedSet<E> createDescendingElementSet() {
+ return new RegularImmutableSortedSet<E>(elementList().reverse(), reverseComparator());
}
+ @SuppressWarnings("unchecked")
@Override
- public int count(@Nullable Object element) {
- int index = elementSet.indexOf(element);
- return (index == -1) ? 0 : counts[index + offset];
+ UnmodifiableIterator<Multiset.Entry<E>> entryIterator() {
+ return (UnmodifiableIterator) entries.iterator();
}
+ @SuppressWarnings("unchecked")
@Override
- public int size() {
- long size = cumulativeCounts[offset + length] - cumulativeCounts[offset];
- return Ints.saturatedCast(size);
+ UnmodifiableIterator<Multiset.Entry<E>> descendingEntryIterator() {
+ return (UnmodifiableIterator) entries.reverse().iterator();
}
@Override
- public ImmutableSortedSet<E> elementSet() {
- return elementSet;
+ public CumulativeCountEntry<E> firstEntry() {
+ return entries.get(0);
}
@Override
- public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
- return getSubMultiset(0, elementSet.headIndex(upperBound, checkNotNull(boundType) == CLOSED));
+ public CumulativeCountEntry<E> lastEntry() {
+ return entries.get(entries.size() - 1);
}
@Override
- public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
- return getSubMultiset(elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED),
- length);
+ public int size() {
+ CumulativeCountEntry<E> firstEntry = firstEntry();
+ CumulativeCountEntry<E> lastEntry = lastEntry();
+ return Ints.saturatedCast(
+ lastEntry.cumulativeCount - firstEntry.cumulativeCount + firstEntry.count);
}
- ImmutableSortedMultiset<E> getSubMultiset(int from, int to) {
- checkPositionIndexes(from, to, length);
- if (from == to) {
- return emptyMultiset(comparator());
- } else if (from == 0 && to == length) {
- return this;
- } else {
- RegularImmutableSortedSet<E> subElementSet =
- (RegularImmutableSortedSet<E>) elementSet.getSubSet(from, to);
- return new RegularImmutableSortedMultiset<E>(
- subElementSet, counts, cumulativeCounts, offset + from, to - from);
- }
+ @Override
+ int distinctElements() {
+ return entries.size();
}
@Override
- ImmutableSet<Entry<E>> createEntrySet() {
- return new EntrySet();
+ boolean isPartialView() {
+ return entries.isPartialView();
}
- private final class EntrySet extends ImmutableMultiset<E>.EntrySet {
- @Override
- public int size() {
- return length;
+ @SuppressWarnings("unchecked")
+ @Override
+ public int count(@Nullable Object element) {
+ if (element == null) {
+ return 0;
}
-
- @Override
- public UnmodifiableIterator<Entry<E>> iterator() {
- return asList().iterator();
+ try {
+ int index = SortedLists.binarySearch(
+ elementList(), (E) element, comparator(), ANY_PRESENT, INVERTED_INSERTION_INDEX);
+ return (index >= 0) ? entries.get(index).getCount() : 0;
+ } catch (ClassCastException e) {
+ return 0;
}
+ }
- @Override
- ImmutableList<Entry<E>> createAsList() {
- return new ImmutableAsList<Entry<E>>() {
- @Override
- public Entry<E> get(int index) {
- return getEntry(index);
- }
-
- @Override
- ImmutableCollection<Entry<E>> delegateCollection() {
- return EntrySet.this;
- }
- };
+ @Override
+ public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) {
+ int index;
+ switch (boundType) {
+ case OPEN:
+ index = SortedLists.binarySearch(
+ elementList(), checkNotNull(upperBound), comparator(), ANY_PRESENT, NEXT_HIGHER);
+ break;
+ case CLOSED:
+ index = SortedLists.binarySearch(
+ elementList(), checkNotNull(upperBound), comparator(), ANY_PRESENT, NEXT_LOWER) + 1;
+ break;
+ default:
+ throw new AssertionError();
}
+ return createSubMultiset(0, index);
}
@Override
- boolean isPartialView() {
- return offset > 0 || length < counts.length;
+ public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) {
+ int index;
+ switch (boundType) {
+ case OPEN:
+ index = SortedLists.binarySearch(
+ elementList(), checkNotNull(lowerBound), comparator(), ANY_PRESENT, NEXT_LOWER) + 1;
+ break;
+ case CLOSED:
+ index = SortedLists.binarySearch(
+ elementList(), checkNotNull(lowerBound), comparator(), ANY_PRESENT, NEXT_HIGHER);
+ break;
+ default:
+ throw new AssertionError();
+ }
+ return createSubMultiset(index, distinctElements());
+ }
+
+ private ImmutableSortedMultiset<E> createSubMultiset(int newFromIndex, int newToIndex) {
+ if (newFromIndex == 0 && newToIndex == entries.size()) {
+ return this;
+ } else if (newFromIndex >= newToIndex) {
+ return emptyMultiset(comparator());
+ } else {
+ return new RegularImmutableSortedMultiset<E>(
+ comparator(), entries.subList(newFromIndex, newToIndex));
+ }
}
}