• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.collect;
18 
19 import static com.google.common.collect.Multisets.setCountImpl;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.base.Objects;
23 
24 import java.util.AbstractCollection;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.Set;
28 
29 import javax.annotation.Nullable;
30 
31 /**
32  * This class provides a skeletal implementation of the {@link Multiset}
33  * interface. A new multiset implementation can be created easily by extending
34  * this class and implementing the {@link Multiset#entrySet()} method, plus
35  * optionally overriding {@link #add(Object, int)} and
36  * {@link #remove(Object, int)} to enable modifications to the multiset.
37  *
38  * <p>The {@link #count} and {@link #size} implementations all iterate across
39  * the set returned by {@link Multiset#entrySet()}, as do many methods acting on
40  * the set returned by {@link #elementSet()}. Override those methods for better
41  * performance.
42  *
43  * @author Kevin Bourrillion
44  * @author Louis Wasserman
45  */
46 @GwtCompatible
47 abstract class AbstractMultiset<E> extends AbstractCollection<E>
48     implements Multiset<E> {
49   // Query Operations
50 
size()51   @Override public int size() {
52     return Multisets.sizeImpl(this);
53   }
54 
isEmpty()55   @Override public boolean isEmpty() {
56     return entrySet().isEmpty();
57   }
58 
contains(@ullable Object element)59   @Override public boolean contains(@Nullable Object element) {
60     return count(element) > 0;
61   }
62 
iterator()63   @Override public Iterator<E> iterator() {
64     return Multisets.iteratorImpl(this);
65   }
66 
67   @Override
count(Object element)68   public int count(Object element) {
69     for (Entry<E> entry : entrySet()) {
70       if (Objects.equal(entry.getElement(), element)) {
71         return entry.getCount();
72       }
73     }
74     return 0;
75   }
76 
77   // Modification Operations
78 
add(@ullable E element)79   @Override public boolean add(@Nullable E element) {
80     add(element, 1);
81     return true;
82   }
83 
84   @Override
add(E element, int occurrences)85   public int add(E element, int occurrences) {
86     throw new UnsupportedOperationException();
87   }
88 
remove(Object element)89   @Override public boolean remove(Object element) {
90     return remove(element, 1) > 0;
91   }
92 
93   @Override
remove(Object element, int occurrences)94   public int remove(Object element, int occurrences) {
95     throw new UnsupportedOperationException();
96   }
97 
98   @Override
setCount(E element, int count)99   public int setCount(E element, int count) {
100     return setCountImpl(this, element, count);
101   }
102 
103   @Override
setCount(E element, int oldCount, int newCount)104   public boolean setCount(E element, int oldCount, int newCount) {
105     return setCountImpl(this, element, oldCount, newCount);
106   }
107 
108   // Bulk Operations
109 
110   /**
111    * {@inheritDoc}
112    *
113    * <p>This implementation is highly efficient when {@code elementsToAdd}
114    * is itself a {@link Multiset}.
115    */
addAll(Collection<? extends E> elementsToAdd)116   @Override public boolean addAll(Collection<? extends E> elementsToAdd) {
117     return Multisets.addAllImpl(this, elementsToAdd);
118   }
119 
removeAll(Collection<?> elementsToRemove)120   @Override public boolean removeAll(Collection<?> elementsToRemove) {
121     return Multisets.removeAllImpl(this, elementsToRemove);
122   }
123 
retainAll(Collection<?> elementsToRetain)124   @Override public boolean retainAll(Collection<?> elementsToRetain) {
125     return Multisets.retainAllImpl(this, elementsToRetain);
126   }
127 
clear()128   @Override public void clear() {
129     Iterators.clear(entryIterator());
130   }
131 
132   // Views
133 
134   private transient Set<E> elementSet;
135 
136   @Override
elementSet()137   public Set<E> elementSet() {
138     Set<E> result = elementSet;
139     if (result == null) {
140       elementSet = result = createElementSet();
141     }
142     return result;
143   }
144 
145   /**
146    * Creates a new instance of this multiset's element set, which will be
147    * returned by {@link #elementSet()}.
148    */
createElementSet()149   Set<E> createElementSet() {
150     return new ElementSet();
151   }
152 
153   class ElementSet extends Multisets.ElementSet<E> {
154     @Override
multiset()155     Multiset<E> multiset() {
156       return AbstractMultiset.this;
157     }
158   }
159 
entryIterator()160   abstract Iterator<Entry<E>> entryIterator();
161 
distinctElements()162   abstract int distinctElements();
163 
164   private transient Set<Entry<E>> entrySet;
165 
entrySet()166   @Override public Set<Entry<E>> entrySet() {
167     Set<Entry<E>> result = entrySet;
168     return (result == null) ? entrySet = createEntrySet() : result;
169   }
170 
171   class EntrySet extends Multisets.EntrySet<E> {
multiset()172     @Override Multiset<E> multiset() {
173       return AbstractMultiset.this;
174     }
175 
iterator()176     @Override public Iterator<Entry<E>> iterator() {
177       return entryIterator();
178     }
179 
size()180     @Override public int size() {
181       return distinctElements();
182     }
183   }
184 
createEntrySet()185   Set<Entry<E>> createEntrySet() {
186     return new EntrySet();
187   }
188 
189   // Object methods
190 
191   /**
192    * {@inheritDoc}
193    *
194    * <p>This implementation returns {@code true} if {@code object} is a multiset
195    * of the same size and if, for each element, the two multisets have the same
196    * count.
197    */
equals(@ullable Object object)198   @Override public boolean equals(@Nullable Object object) {
199     return Multisets.equalsImpl(this, object);
200   }
201 
202   /**
203    * {@inheritDoc}
204    *
205    * <p>This implementation returns the hash code of {@link
206    * Multiset#entrySet()}.
207    */
hashCode()208   @Override public int hashCode() {
209     return entrySet().hashCode();
210   }
211 
212   /**
213    * {@inheritDoc}
214    *
215    * <p>This implementation returns the result of invoking {@code toString} on
216    * {@link Multiset#entrySet()}.
217    */
toString()218   @Override public String toString() {
219     return entrySet().toString();
220   }
221 }
222