RegularImmutableSortedMultiset.java revision 3c77433663281544363151bf284b0240dfd22a42
1/* 2 * Copyright (C) 2011 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 11 * express or implied. See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15package com.google.common.collect; 16 17import static com.google.common.base.Preconditions.checkNotNull; 18import static com.google.common.base.Preconditions.checkPositionIndexes; 19import static com.google.common.collect.BoundType.CLOSED; 20 21import com.google.common.primitives.Ints; 22 23import javax.annotation.Nullable; 24 25/** 26 * An immutable sorted multiset with one or more distinct elements. 27 * 28 * @author Louis Wasserman 29 */ 30@SuppressWarnings("serial") // uses writeReplace, not default serialization 31final class RegularImmutableSortedMultiset<E> extends ImmutableSortedMultiset<E> { 32 private final transient RegularImmutableSortedSet<E> elementSet; 33 private final transient int[] counts; 34 private final transient long[] cumulativeCounts; 35 private final transient int offset; 36 private final transient int length; 37 38 RegularImmutableSortedMultiset( 39 RegularImmutableSortedSet<E> elementSet, 40 int[] counts, 41 long[] cumulativeCounts, 42 int offset, 43 int length) { 44 this.elementSet = elementSet; 45 this.counts = counts; 46 this.cumulativeCounts = cumulativeCounts; 47 this.offset = offset; 48 this.length = length; 49 } 50 51 private Entry<E> getEntry(int index) { 52 return Multisets.immutableEntry( 53 elementSet.asList().get(index), 54 counts[offset + index]); 55 } 56 57 @Override 58 public Entry<E> firstEntry() { 59 return getEntry(0); 60 } 61 62 @Override 63 public Entry<E> lastEntry() { 64 return getEntry(length - 1); 65 } 66 67 @Override 68 public int count(@Nullable Object element) { 69 int index = elementSet.indexOf(element); 70 return (index == -1) ? 0 : counts[index + offset]; 71 } 72 73 @Override 74 public int size() { 75 long size = cumulativeCounts[offset + length] - cumulativeCounts[offset]; 76 return Ints.saturatedCast(size); 77 } 78 79 @Override 80 public ImmutableSortedSet<E> elementSet() { 81 return elementSet; 82 } 83 84 @Override 85 public ImmutableSortedMultiset<E> headMultiset(E upperBound, BoundType boundType) { 86 return getSubMultiset(0, elementSet.headIndex(upperBound, checkNotNull(boundType) == CLOSED)); 87 } 88 89 @Override 90 public ImmutableSortedMultiset<E> tailMultiset(E lowerBound, BoundType boundType) { 91 return getSubMultiset(elementSet.tailIndex(lowerBound, checkNotNull(boundType) == CLOSED), 92 length); 93 } 94 95 ImmutableSortedMultiset<E> getSubMultiset(int from, int to) { 96 checkPositionIndexes(from, to, length); 97 if (from == to) { 98 return emptyMultiset(comparator()); 99 } else if (from == 0 && to == length) { 100 return this; 101 } else { 102 RegularImmutableSortedSet<E> subElementSet = 103 (RegularImmutableSortedSet<E>) elementSet.getSubSet(from, to); 104 return new RegularImmutableSortedMultiset<E>( 105 subElementSet, counts, cumulativeCounts, offset + from, to - from); 106 } 107 } 108 109 @Override 110 ImmutableSet<Entry<E>> createEntrySet() { 111 return new EntrySet(); 112 } 113 114 private final class EntrySet extends ImmutableMultiset<E>.EntrySet { 115 @Override 116 public int size() { 117 return length; 118 } 119 120 @Override 121 public UnmodifiableIterator<Entry<E>> iterator() { 122 return asList().iterator(); 123 } 124 125 @Override 126 ImmutableList<Entry<E>> createAsList() { 127 return new ImmutableAsList<Entry<E>>() { 128 @Override 129 public Entry<E> get(int index) { 130 return getEntry(index); 131 } 132 133 @Override 134 ImmutableCollection<Entry<E>> delegateCollection() { 135 return EntrySet.this; 136 } 137 }; 138 } 139 } 140 141 @Override 142 boolean isPartialView() { 143 return offset > 0 || length < counts.length; 144 } 145} 146