Home | History | Annotate | Download | only in collect
      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 import com.google.common.collect.Multiset.Entry;
     21 
     22 import java.io.Serializable;
     23 import java.util.Iterator;
     24 import java.util.Map;
     25 import java.util.concurrent.atomic.AtomicInteger;
     26 
     27 /**
     28  * Unit test for {@link AbstractMultiset}.
     29  *
     30  * @author Kevin Bourrillion
     31  * @author Louis Wasserman
     32  */
     33 @SuppressWarnings("serial") // No serialization is used in this test
     34 @GwtCompatible
     35 public class SimpleAbstractMultisetTest extends AbstractMultisetTest {
     36 
     37   @Override protected <E> Multiset<E> create() {
     38     return new SimpleAbstractMultiset<E>();
     39   }
     40 
     41   public void testFastAddAllMultiset() {
     42     final AtomicInteger addCalls = new AtomicInteger();
     43     Multiset<String> multiset = new NoRemoveMultiset<String>() {
     44       @Override
     45       public int add(String element, int occurrences) {
     46         addCalls.incrementAndGet();
     47         return super.add(element, occurrences);
     48       }
     49     };
     50     ImmutableMultiset<String> adds =
     51         new ImmutableMultiset.Builder<String>().addCopies("x", 10).build();
     52     multiset.addAll(adds);
     53     assertEquals(addCalls.get(), 1);
     54   }
     55 
     56   public void testRemoveUnsupported() {
     57     Multiset<String> multiset = new NoRemoveMultiset<String>();
     58     multiset.add("a");
     59     try {
     60       multiset.remove("a");
     61       fail();
     62     } catch (UnsupportedOperationException expected) {}
     63     assertTrue(multiset.contains("a"));
     64   }
     65 
     66   private static class NoRemoveMultiset<E> extends AbstractMultiset<E>
     67       implements Serializable {
     68     final Map<E, Integer> backingMap = Maps.newHashMap();
     69 
     70     @Override public int add(E element, int occurrences) {
     71       checkArgument(occurrences >= 0);
     72       Integer frequency = backingMap.get(element);
     73       if (frequency == null) {
     74         frequency = 0;
     75       }
     76       if (occurrences == 0) {
     77         return frequency;
     78       }
     79       checkArgument(occurrences <= Integer.MAX_VALUE - frequency);
     80       backingMap.put(element, frequency + occurrences);
     81       return frequency;
     82     }
     83 
     84     @Override
     85     Iterator<Entry<E>> entryIterator() {
     86       final Iterator<Map.Entry<E, Integer>> backingEntries = backingMap.entrySet().iterator();
     87       return new Iterator<Multiset.Entry<E>>() {
     88         @Override
     89         public boolean hasNext() {
     90           return backingEntries.hasNext();
     91         }
     92 
     93         @Override
     94         public Multiset.Entry<E> next() {
     95           final Map.Entry<E, Integer> mapEntry = backingEntries.next();
     96           return new Multisets.AbstractEntry<E>() {
     97             @Override
     98             public E getElement() {
     99               return mapEntry.getKey();
    100             }
    101 
    102             @Override
    103             public int getCount() {
    104               Integer frequency = backingMap.get(getElement());
    105               return (frequency == null) ? 0 : frequency;
    106             }
    107           };
    108         }
    109 
    110         @Override
    111         public void remove() {
    112           backingEntries.remove();
    113         }
    114       };
    115     }
    116 
    117     @Override
    118     int distinctElements() {
    119       return backingMap.size();
    120     }
    121   }
    122 
    123   private static class SimpleAbstractMultiset<E> extends NoRemoveMultiset<E> {
    124     @SuppressWarnings("unchecked")
    125     @Override public int remove(Object element, int occurrences) {
    126       checkArgument(occurrences >= 0);
    127       Integer count = backingMap.get(element);
    128       if (count == null) {
    129         return 0;
    130       } else if (count > occurrences) {
    131         backingMap.put((E) element, count - occurrences);
    132         return count;
    133       } else {
    134         return backingMap.remove(element);
    135       }
    136     }
    137   }
    138 }
    139