| /* |
| * Copyright (C) 2007 The Guava Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| |
| package com.google.common.collect; |
| |
| import static com.google.common.base.Preconditions.checkArgument; |
| |
| import com.google.common.annotations.GwtCompatible; |
| import com.google.common.annotations.GwtIncompatible; |
| import com.google.common.collect.testing.features.CollectionFeature; |
| import com.google.common.collect.testing.features.CollectionSize; |
| import com.google.common.collect.testing.google.MultisetTestSuiteBuilder; |
| import com.google.common.collect.testing.google.TestStringMultisetGenerator; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| |
| import java.io.Serializable; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import javax.annotation.Nullable; |
| |
| /** |
| * Unit test for {@link AbstractMultiset}. |
| * |
| * @author Kevin Bourrillion |
| * @author Louis Wasserman |
| */ |
| @SuppressWarnings("serial") // No serialization is used in this test |
| @GwtCompatible(emulated = true) |
| public class SimpleAbstractMultisetTest extends TestCase { |
| @GwtIncompatible("suite") |
| public static Test suite() { |
| TestSuite suite = new TestSuite(); |
| suite.addTestSuite(SimpleAbstractMultisetTest.class); |
| suite.addTest(MultisetTestSuiteBuilder.using(new TestStringMultisetGenerator() { |
| @Override |
| protected Multiset<String> create(String[] elements) { |
| Multiset<String> ms = new NoRemoveMultiset<String>(); |
| Collections.addAll(ms, elements); |
| return ms; |
| } |
| }) |
| .named("NoRemoveMultiset") |
| .withFeatures(CollectionSize.ANY, CollectionFeature.ALLOWS_NULL_VALUES, |
| CollectionFeature.SUPPORTS_ADD) |
| .createTestSuite()); |
| return suite; |
| } |
| |
| public void testFastAddAllMultiset() { |
| final AtomicInteger addCalls = new AtomicInteger(); |
| Multiset<String> multiset = new NoRemoveMultiset<String>() { |
| @Override |
| public int add(String element, int occurrences) { |
| addCalls.incrementAndGet(); |
| return super.add(element, occurrences); |
| } |
| }; |
| ImmutableMultiset<String> adds = |
| new ImmutableMultiset.Builder<String>().addCopies("x", 10).build(); |
| multiset.addAll(adds); |
| assertEquals(addCalls.get(), 1); |
| } |
| |
| public void testRemoveUnsupported() { |
| Multiset<String> multiset = new NoRemoveMultiset<String>(); |
| multiset.add("a"); |
| try { |
| multiset.remove("a"); |
| fail(); |
| } catch (UnsupportedOperationException expected) {} |
| assertTrue(multiset.contains("a")); |
| } |
| |
| private static class NoRemoveMultiset<E> extends AbstractMultiset<E> |
| implements Serializable { |
| final Map<E, Integer> backingMap = Maps.newHashMap(); |
| |
| @Override public int add(@Nullable E element, int occurrences) { |
| checkArgument(occurrences >= 0); |
| Integer frequency = backingMap.get(element); |
| if (frequency == null) { |
| frequency = 0; |
| } |
| if (occurrences == 0) { |
| return frequency; |
| } |
| checkArgument(occurrences <= Integer.MAX_VALUE - frequency); |
| backingMap.put(element, frequency + occurrences); |
| return frequency; |
| } |
| |
| @Override |
| Iterator<Entry<E>> entryIterator() { |
| final Iterator<Map.Entry<E, Integer>> backingEntries = backingMap.entrySet().iterator(); |
| return new UnmodifiableIterator<Multiset.Entry<E>>() { |
| @Override |
| public boolean hasNext() { |
| return backingEntries.hasNext(); |
| } |
| |
| @Override |
| public Multiset.Entry<E> next() { |
| final Map.Entry<E, Integer> mapEntry = backingEntries.next(); |
| return new Multisets.AbstractEntry<E>() { |
| @Override |
| public E getElement() { |
| return mapEntry.getKey(); |
| } |
| |
| @Override |
| public int getCount() { |
| Integer frequency = backingMap.get(getElement()); |
| return (frequency == null) ? 0 : frequency; |
| } |
| }; |
| } |
| }; |
| } |
| |
| @Override |
| int distinctElements() { |
| return backingMap.size(); |
| } |
| } |
| } |