View Javadoc
1   /*
2    * Copyright (C) 2007 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 static com.google.common.base.Preconditions.checkArgument;
18  
19  import com.google.common.annotations.GwtCompatible;
20  
21  import junit.framework.TestCase;
22  
23  import java.io.Serializable;
24  import java.util.Iterator;
25  import java.util.Map;
26  import java.util.concurrent.atomic.AtomicInteger;
27  
28  import javax.annotation.Nullable;
29  
30  /**
31   * Unit test for {@link AbstractMultiset}.
32   *
33   * @author Kevin Bourrillion
34   * @author Louis Wasserman
35   */
36  @SuppressWarnings("serial") // No serialization is used in this test
37  @GwtCompatible(emulated = true)
38  public class SimpleAbstractMultisetTest extends TestCase {
39  
40    public void testFastAddAllMultiset() {
41      final AtomicInteger addCalls = new AtomicInteger();
42      Multiset<String> multiset = new NoRemoveMultiset<String>() {
43        @Override
44        public int add(String element, int occurrences) {
45          addCalls.incrementAndGet();
46          return super.add(element, occurrences);
47        }
48      };
49      ImmutableMultiset<String> adds =
50          new ImmutableMultiset.Builder<String>().addCopies("x", 10).build();
51      multiset.addAll(adds);
52      assertEquals(addCalls.get(), 1);
53    }
54  
55    public void testRemoveUnsupported() {
56      Multiset<String> multiset = new NoRemoveMultiset<String>();
57      multiset.add("a");
58      try {
59        multiset.remove("a");
60        fail();
61      } catch (UnsupportedOperationException expected) {}
62      assertTrue(multiset.contains("a"));
63    }
64  
65    private static class NoRemoveMultiset<E> extends AbstractMultiset<E>
66        implements Serializable {
67      final Map<E, Integer> backingMap = Maps.newHashMap();
68  
69      @Override public int add(@Nullable E element, int occurrences) {
70        checkArgument(occurrences >= 0);
71        Integer frequency = backingMap.get(element);
72        if (frequency == null) {
73          frequency = 0;
74        }
75        if (occurrences == 0) {
76          return frequency;
77        }
78        checkArgument(occurrences <= Integer.MAX_VALUE - frequency);
79        backingMap.put(element, frequency + occurrences);
80        return frequency;
81      }
82  
83      @Override
84      Iterator<Entry<E>> entryIterator() {
85        final Iterator<Map.Entry<E, Integer>> backingEntries = backingMap.entrySet().iterator();
86        return new UnmodifiableIterator<Multiset.Entry<E>>() {
87          @Override
88          public boolean hasNext() {
89            return backingEntries.hasNext();
90          }
91  
92          @Override
93          public Multiset.Entry<E> next() {
94            final Map.Entry<E, Integer> mapEntry = backingEntries.next();
95            return new Multisets.AbstractEntry<E>() {
96              @Override
97              public E getElement() {
98                return mapEntry.getKey();
99              }
100 
101             @Override
102             public int getCount() {
103               Integer frequency = backingMap.get(getElement());
104               return (frequency == null) ? 0 : frequency;
105             }
106           };
107         }
108       };
109     }
110 
111     @Override
112     int distinctElements() {
113       return backingMap.size();
114     }
115   }
116 }
117