• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.common.collect;
16 
17 import com.google.common.annotations.GwtCompatible;
18 import com.google.common.annotations.GwtIncompatible;
19 import com.google.common.annotations.J2ktIncompatible;
20 import com.google.common.collect.Multiset.Entry;
21 import com.google.common.primitives.Ints;
22 import com.google.errorprone.annotations.concurrent.LazyInit;
23 import com.google.j2objc.annotations.WeakOuter;
24 import java.io.Serializable;
25 import javax.annotation.CheckForNull;
26 
27 /**
28  * Implementation of {@link ImmutableMultiset} with zero or more elements.
29  *
30  * @author Jared Levy
31  * @author Louis Wasserman
32  */
33 @GwtCompatible(emulated = true, serializable = true)
34 @SuppressWarnings("serial") // uses writeReplace(), not default serialization
35 @ElementTypesAreNonnullByDefault
36 class RegularImmutableMultiset<E> extends ImmutableMultiset<E> {
37   static final RegularImmutableMultiset<Object> EMPTY =
38       new RegularImmutableMultiset<>(ObjectCountHashMap.create());
39 
40   final transient ObjectCountHashMap<E> contents;
41   private final transient int size;
42 
43   @LazyInit @CheckForNull private transient ImmutableSet<E> elementSet;
44 
RegularImmutableMultiset(ObjectCountHashMap<E> contents)45   RegularImmutableMultiset(ObjectCountHashMap<E> contents) {
46     this.contents = contents;
47     long size = 0;
48     for (int i = 0; i < contents.size(); i++) {
49       size += contents.getValue(i);
50     }
51     this.size = Ints.saturatedCast(size);
52   }
53 
54   @Override
isPartialView()55   boolean isPartialView() {
56     return false;
57   }
58 
59   @Override
count(@heckForNull Object element)60   public int count(@CheckForNull Object element) {
61     return contents.get(element);
62   }
63 
64   @Override
size()65   public int size() {
66     return size;
67   }
68 
69   @Override
elementSet()70   public ImmutableSet<E> elementSet() {
71     ImmutableSet<E> result = elementSet;
72     return (result == null) ? elementSet = new ElementSet() : result;
73   }
74 
75   @WeakOuter
76   private final class ElementSet extends IndexedImmutableSet<E> {
77 
78     @Override
get(int index)79     E get(int index) {
80       return contents.getKey(index);
81     }
82 
83     @Override
contains(@heckForNull Object object)84     public boolean contains(@CheckForNull Object object) {
85       return RegularImmutableMultiset.this.contains(object);
86     }
87 
88     @Override
isPartialView()89     boolean isPartialView() {
90       return true;
91     }
92 
93     @Override
size()94     public int size() {
95       return contents.size();
96     }
97 
98     // redeclare to help optimizers with b/310253115
99     @SuppressWarnings("RedundantOverride")
100     @Override
101     @J2ktIncompatible // serialization
102     @GwtIncompatible // serialization
writeReplace()103     Object writeReplace() {
104       return super.writeReplace();
105     }
106   }
107 
108   @Override
getEntry(int index)109   Entry<E> getEntry(int index) {
110     return contents.getEntry(index);
111   }
112 
113   @GwtIncompatible
114   private static class SerializedForm implements Serializable {
115     final Object[] elements;
116     final int[] counts;
117 
118     // "extends Object" works around https://github.com/typetools/checker-framework/issues/3013
SerializedForm(Multiset<? extends Object> multiset)119     SerializedForm(Multiset<? extends Object> multiset) {
120       int distinct = multiset.entrySet().size();
121       elements = new Object[distinct];
122       counts = new int[distinct];
123       int i = 0;
124       for (Entry<? extends Object> entry : multiset.entrySet()) {
125         elements[i] = entry.getElement();
126         counts[i] = entry.getCount();
127         i++;
128       }
129     }
130 
readResolve()131     Object readResolve() {
132       ImmutableMultiset.Builder<Object> builder =
133           new ImmutableMultiset.Builder<Object>(elements.length);
134       for (int i = 0; i < elements.length; i++) {
135         builder.addCopies(elements[i], counts[i]);
136       }
137       return builder.build();
138     }
139 
140     private static final long serialVersionUID = 0;
141   }
142 
143   @Override
144   @J2ktIncompatible // serialization
145   @GwtIncompatible // serialization
writeReplace()146   Object writeReplace() {
147     return new SerializedForm(this);
148   }
149 }
150