1
2
3
4
5
6
7
8
9
10
11
12
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 import com.google.common.annotations.GwtIncompatible;
21 import com.google.common.collect.testing.features.CollectionFeature;
22 import com.google.common.collect.testing.features.CollectionSize;
23 import com.google.common.collect.testing.google.MultisetTestSuiteBuilder;
24 import com.google.common.collect.testing.google.TestStringMultisetGenerator;
25
26 import junit.framework.Test;
27 import junit.framework.TestCase;
28 import junit.framework.TestSuite;
29
30 import java.io.Serializable;
31 import java.util.Collections;
32 import java.util.Iterator;
33 import java.util.Map;
34 import java.util.concurrent.atomic.AtomicInteger;
35
36 import javax.annotation.Nullable;
37
38
39
40
41
42
43
44 @SuppressWarnings("serial")
45 @GwtCompatible(emulated = true)
46 public class SimpleAbstractMultisetTest extends TestCase {
47 @GwtIncompatible("suite")
48 public static Test suite() {
49 TestSuite suite = new TestSuite();
50 suite.addTestSuite(SimpleAbstractMultisetTest.class);
51 suite.addTest(MultisetTestSuiteBuilder.using(new TestStringMultisetGenerator() {
52 @Override
53 protected Multiset<String> create(String[] elements) {
54 Multiset<String> ms = new NoRemoveMultiset<String>();
55 Collections.addAll(ms, elements);
56 return ms;
57 }
58 })
59 .named("NoRemoveMultiset")
60 .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES,
61 CollectionFeature.SUPPORTS_ADD)
62 .createTestSuite());
63 return suite;
64 }
65
66 public void testFastAddAllMultiset() {
67 final AtomicInteger addCalls = new AtomicInteger();
68 Multiset<String> multiset = new NoRemoveMultiset<String>() {
69 @Override
70 public int add(String element, int occurrences) {
71 addCalls.incrementAndGet();
72 return super.add(element, occurrences);
73 }
74 };
75 ImmutableMultiset<String> adds =
76 new ImmutableMultiset.Builder<String>().addCopies("x", 10).build();
77 multiset.addAll(adds);
78 assertEquals(addCalls.get(), 1);
79 }
80
81 public void testRemoveUnsupported() {
82 Multiset<String> multiset = new NoRemoveMultiset<String>();
83 multiset.add("a");
84 try {
85 multiset.remove("a");
86 fail();
87 } catch (UnsupportedOperationException expected) {}
88 assertTrue(multiset.contains("a"));
89 }
90
91 private static class NoRemoveMultiset<E> extends AbstractMultiset<E>
92 implements Serializable {
93 final Map<E, Integer> backingMap = Maps.newHashMap();
94
95 @Override public int add(@Nullable E element, int occurrences) {
96 checkArgument(occurrences >= 0);
97 Integer frequency = backingMap.get(element);
98 if (frequency == null) {
99 frequency = 0;
100 }
101 if (occurrences == 0) {
102 return frequency;
103 }
104 checkArgument(occurrences <= Integer.MAX_VALUE - frequency);
105 backingMap.put(element, frequency + occurrences);
106 return frequency;
107 }
108
109 @Override
110 Iterator<Entry<E>> entryIterator() {
111 final Iterator<Map.Entry<E, Integer>> backingEntries = backingMap.entrySet().iterator();
112 return new UnmodifiableIterator<Multiset.Entry<E>>() {
113 @Override
114 public boolean hasNext() {
115 return backingEntries.hasNext();
116 }
117
118 @Override
119 public Multiset.Entry<E> next() {
120 final Map.Entry<E, Integer> mapEntry = backingEntries.next();
121 return new Multisets.AbstractEntry<E>() {
122 @Override
123 public E getElement() {
124 return mapEntry.getKey();
125 }
126
127 @Override
128 public int getCount() {
129 Integer frequency = backingMap.get(getElement());
130 return (frequency == null) ? 0 : frequency;
131 }
132 };
133 }
134 };
135 }
136
137 @Override
138 int distinctElements() {
139 return backingMap.size();
140 }
141 }
142 }