/** * Delegate implementation which cares about the element type. */ private static <E> boolean retainOccurrencesImpl( Multiset<E> multisetToModify, Multiset<?> occurrencesToRetain) { checkNotNull(multisetToModify); checkNotNull(occurrencesToRetain); // Avoiding ConcurrentModificationExceptions is tricky. Iterator<Entry<E>> entryIterator = multisetToModify.entrySet().iterator(); boolean changed = false; while (entryIterator.hasNext()) { Entry<E> entry = entryIterator.next(); int retainCount = occurrencesToRetain.count(entry.getElement()); if (retainCount == 0) { entryIterator.remove(); changed = true; } else if (retainCount < entry.getCount()) { multisetToModify.setCount(entry.getElement(), retainCount); changed = true; } } return changed; }
/** * An implementation of {@link Multiset#equals}. */ static boolean equalsImpl(Multiset<?> multiset, @Nullable Object object) { if (object == multiset) { return true; } if (object instanceof Multiset) { Multiset<?> that = (Multiset<?>) object; /* * We can't simply check whether the entry sets are equal, since that * approach fails when a TreeMultiset has a comparator that returns 0 * when passed unequal elements. */ if (multiset.size() != that.size() || multiset.entrySet().size() != that.entrySet().size()) { return false; } for (Entry<?> entry : that.entrySet()) { if (multiset.count(entry.getElement()) != entry.getCount()) { return false; } } return true; } return false; }
@SuppressWarnings("cast") @Override public boolean remove(Object object) { if (object instanceof Multiset.Entry) { Entry<?> entry = (Entry<?>) object; Object element = entry.getElement(); int entryCount = entry.getCount(); if (entryCount != 0) { // Safe as long as we never add a new entry, which we won't. @SuppressWarnings("unchecked") Multiset<Object> multiset = (Multiset) multiset(); return multiset.setCount(element, entryCount, 0); } } return false; }
/** * Passes this Packet on to the NetHandler for processing. */ @Override public void processPacket(INetHandler inethandler) { this.netHandler = inethandler; EmbeddedChannel internalChannel = NetworkRegistry.INSTANCE.getChannel(this.channel, this.target); if (internalChannel != null) { internalChannel.attr(NetworkRegistry.NET_HANDLER).set(this.netHandler); try { if (internalChannel.writeInbound(this)) { badPackets.add(this.channel); if (badPackets.size() % packetCountWarning == 0) { FMLLog.severe("Detected ongoing potential memory leak. %d packets have leaked. Top offenders", badPackets.size()); int i = 0; for (Entry<String> s : Multisets.copyHighestCountFirst(badPackets).entrySet()) { if (i++ > 10) break; FMLLog.severe("\t %s : %d", s.getElement(), s.getCount()); } } } internalChannel.inboundMessages().clear(); } catch (FMLNetworkException ne) { FMLLog.log(Level.ERROR, ne, "There was a network exception handling a packet on channel %s", channel); dispatcher.rejectHandshake(ne.getMessage()); } catch (Throwable t) { FMLLog.log(Level.ERROR, t, "There was a critical exception handling a packet on channel %s", channel); dispatcher.rejectHandshake("A fatal error has occurred, this connection is terminated"); } } }
@Override public boolean contains(@Nullable Object o) { if (o instanceof Entry) { /* * The GWT compiler wrongly issues a warning here. */ @SuppressWarnings("cast") Entry<?> entry = (Entry<?>) o; if (entry.getCount() <= 0) { return false; } int count = multiset().count(entry.getElement()); return count == entry.getCount(); } return false; }
private void assertSetCount(E element, int count) { setCountCheckReturnValue(element, count); assertEquals( "multiset.count() should return the value passed to setCount()", count, getMultiset().count(element)); int size = 0; for (Multiset.Entry<E> entry : getMultiset().entrySet()) { size += entry.getCount(); } assertEquals( "multiset.size() should be the sum of the counts of all entries", size, getMultiset().size()); }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearHeadOpen() { List<Entry<E>> expected = copyToList(sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet()); sortedMultiset.headMultiset(b.getElement(), OPEN).clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
@SuppressWarnings("unchecked") @Override public Set<Multiset.Entry<E>> entrySet() { Set<Multiset.Entry<E>> es = entrySet; return (es == null) // Safe because the returned set is made unmodifiable and Entry // itself is readonly ? entrySet = (Set) Collections.unmodifiableSet(delegate.entrySet()) : es; }
@Override Set<Entry<E>> createEntrySet() { return Sets.filter( unfiltered.entrySet(), new Predicate<Entry<E>>() { @Override public boolean apply(Entry<E> entry) { return predicate.apply(entry.getElement()); } }); }
/** * Indicates whether an object equals this entry, following the behavior * specified in {@link Multiset.Entry#equals}. */ @Override public boolean equals(@Nullable Object object) { if (object instanceof Multiset.Entry) { Multiset.Entry<?> that = (Multiset.Entry<?>) object; return this.getCount() == that.getCount() && Objects.equal(this.getElement(), that.getElement()); } return false; }
/** * An implementation of {@link Multiset#addAll}. */ static <E> boolean addAllImpl(Multiset<E> self, Collection<? extends E> elements) { if (elements.isEmpty()) { return false; } if (elements instanceof Multiset) { Multiset<? extends E> that = cast(elements); for (Entry<? extends E> entry : that.entrySet()) { self.add(entry.getElement(), entry.getCount()); } } else { Iterators.addAll(self, elements.iterator()); } return true; }
@Override public Iterator<E> iterator() { return new TransformedIterator<Entry<E>, E>(multiset().entrySet().iterator()) { @Override E transform(Entry<E> entry) { return entry.getElement(); } }; }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearHeadClosedEntrySet() { List<Entry<E>> expected = copyToList(sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet()); sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet().clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
static <E> Spliterator<E> spliteratorImpl(Multiset<E> multiset) { Spliterator<Entry<E>> entrySpliterator = multiset.entrySet().spliterator(); return CollectSpliterators.flatMap( entrySpliterator, entry -> Collections.nCopies(entry.getCount(), entry.getElement()).spliterator(), Spliterator.SIZED | (entrySpliterator.characteristics() & (Spliterator.ORDERED | Spliterator.NONNULL | Spliterator.IMMUTABLE)), multiset.size()); }
/** * An implementation of {@link Multiset#size}. */ static int sizeImpl(Multiset<?> multiset) { long size = 0; for (Entry<?> entry : multiset.entrySet()) { size += entry.getCount(); } return Ints.saturatedCast(size); }
/** * Returns a copy of {@code multiset} as an {@link ImmutableMultiset} whose iteration order is * highest count first, with ties broken by the iteration order of the original multiset. * * @since 11.0 */ @Beta public static <E> ImmutableMultiset<E> copyHighestCountFirst(Multiset<E> multiset) { Entry<E>[] entries = (Entry<E>[]) multiset.entrySet().toArray(new Entry[0]); Arrays.sort(entries, DecreasingCount.INSTANCE); return ImmutableMultiset.copyFromEntries(Arrays.asList(entries)); }
@CollectionFeature.Require(KNOWN_ORDER) public void testForEachEntryOrdered() { List<Entry<E>> expected = new ArrayList<>(getMultiset().entrySet()); List<Entry<E>> actual = new ArrayList<>(); getMultiset() .forEachEntry((element, count) -> actual.add(Multisets.immutableEntry(element, count))); assertEquals(expected, actual); }
public void testForEachEntryDuplicates() { initThreeCopies(); List<Entry<E>> expected = Collections.singletonList(Multisets.immutableEntry(e0(), 3)); List<Entry<E>> actual = new ArrayList<>(); getMultiset() .forEachEntry((element, count) -> actual.add(Multisets.immutableEntry(element, count))); assertEquals(expected, actual); }
private void testSubMultisetSize(SubMultisetSpec spec) { List<Entry<E>> entries = copyToList(sortedMultiset.entrySet()); for (int i = 0; i < entries.size(); i++) { List<Entry<E>> expected = spec.expectedEntries(i, entries); SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i); assertEquals(totalSize(expected), subMultiset.size()); } }
@CollectionFeature.Require({SUPPORTS_ADD, FAILS_FAST_ON_CONCURRENT_MODIFICATION}) public void testSetCountZeroToOneConcurrentWithEntrySetIteration() { try { Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator(); assertSetCount(e3(), 1); iterator.next(); fail("Expected ConcurrentModificationException"); } catch (ConcurrentModificationException expected) { // success } }
@CollectionFeature.Require({SUPPORTS_REMOVE, FAILS_FAST_ON_CONCURRENT_MODIFICATION}) @CollectionSize.Require(absent = ZERO) public void testSetCountOneToZeroConcurrentWithEntrySetIteration() { try { Iterator<Entry<E>> iterator = getMultiset().entrySet().iterator(); assertSetCount(e0(), 0); iterator.next(); fail("Expected ConcurrentModificationException"); } catch (ConcurrentModificationException expected) { // success } }
@Override public Set<Multiset.Entry<E>> create(Object... entries) { List<Object> contents = new ArrayList<Object>(); Set<E> elements = new HashSet<E>(); for (Object o : entries) { @SuppressWarnings("unchecked") Multiset.Entry<E> entry = (Entry<E>) o; checkArgument( elements.add(entry.getElement()), "Duplicate keys not allowed in EntrySetGenerator"); for (int i = 0; i < entry.getCount(); i++) { contents.add(entry.getElement()); } } return ((Multiset<E>) gen.create(contents.toArray())).entrySet(); }
@CollectionSize.Require(SEVERAL) public void testDescendingNavigation() { List<Entry<E>> ascending = new ArrayList<Entry<E>>(); Iterators.addAll(ascending, sortedMultiset.entrySet().iterator()); List<Entry<E>> descending = new ArrayList<Entry<E>>(); Iterators.addAll(descending, sortedMultiset.descendingMultiset().entrySet().iterator()); Collections.reverse(descending); assertEquals(ascending, descending); }
void expectSetCountFailure(SortedMultiset<E> multiset, Entry<E> entry) { try { multiset.setCount(entry.getElement(), multiset.count(entry.getElement())); } catch (IllegalArgumentException acceptable) { } try { multiset.setCount(entry.getElement(), multiset.count(entry.getElement()) + 1); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException expected) { } }
private static int totalSize(Iterable<? extends Entry<?>> entries) { int sum = 0; for (Entry<?> entry : entries) { sum += entry.getCount(); } return sum; }
private void testSubMultisetEntrySet(SubMultisetSpec spec) { List<Entry<E>> entries = copyToList(sortedMultiset.entrySet()); for (int i = 0; i < entries.size(); i++) { List<Entry<E>> expected = spec.expectedEntries(i, entries); SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i); assertEquals(expected, copyToList(subMultiset.entrySet())); } }
private void testSubMultisetDistinctElements(SubMultisetSpec spec) { List<Entry<E>> entries = copyToList(sortedMultiset.entrySet()); for (int i = 0; i < entries.size(); i++) { List<Entry<E>> expected = spec.expectedEntries(i, entries); SortedMultiset<E> subMultiset = spec.subMultiset(sortedMultiset, entries, i); assertEquals(expected.size(), subMultiset.entrySet().size()); assertEquals(expected.size(), subMultiset.elementSet().size()); } }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearTailOpen() { List<Entry<E>> expected = copyToList(sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet()); sortedMultiset.tailMultiset(b.getElement(), OPEN).clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearTailOpenEntrySet() { List<Entry<E>> expected = copyToList(sortedMultiset.headMultiset(b.getElement(), CLOSED).entrySet()); sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet().clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearTailClosedEntrySet() { List<Entry<E>> expected = copyToList(sortedMultiset.headMultiset(b.getElement(), OPEN).entrySet()); sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet().clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearHeadOpenEntrySet() { List<Entry<E>> expected = copyToList(sortedMultiset.tailMultiset(b.getElement(), CLOSED).entrySet()); sortedMultiset.headMultiset(b.getElement(), OPEN).entrySet().clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
@CollectionSize.Require(SEVERAL) @CollectionFeature.Require(SUPPORTS_REMOVE) public void testClearHeadClosed() { List<Entry<E>> expected = copyToList(sortedMultiset.tailMultiset(b.getElement(), OPEN).entrySet()); sortedMultiset.headMultiset(b.getElement(), CLOSED).clear(); assertEquals(expected, copyToList(sortedMultiset.entrySet())); }
public void testForEachEntry() { ImmutableSortedMultiset<String> multiset = ImmutableSortedMultiset.<String>naturalOrder().add("a").add("b").add("a").add("c").build(); List<Multiset.Entry<String>> entries = new ArrayList<>(); multiset.forEachEntry((e, c) -> entries.add(Multisets.immutableEntry(e, c))); assertThat(entries) .containsExactly( Multisets.immutableEntry("a", 2), Multisets.immutableEntry("b", 1), Multisets.immutableEntry("c", 1)) .inOrder(); }
@SuppressWarnings("unchecked") public void testCopyOfSortedDefensiveCopy() { // Depending on JDK version, either toArray() or toArray(T[]) may be called... use this class // rather than mocking to ensure that one of those methods is called. class TestHashSet<E> extends HashSet<E> { boolean toArrayCalled = false; @Override public Object[] toArray() { toArrayCalled = true; return super.toArray(); } @Override public <T> T[] toArray(T[] a) { toArrayCalled = true; return super.toArray(a); } } // Test that toArray() is used to make a defensive copy in copyOf(), so concurrently modified // synchronized collections can be safely copied. SortedMultiset<String> toCopy = mock(SortedMultiset.class); TestHashSet<Entry<String>> entrySet = new TestHashSet<Entry<String>>(); when((Comparator<Comparable<String>>) toCopy.comparator()) .thenReturn(Ordering.<Comparable<String>>natural()); when(toCopy.entrySet()).thenReturn(entrySet); ImmutableSortedMultiset<String> unused = ImmutableSortedMultiset.copyOfSorted(toCopy); assertTrue(entrySet.toArrayCalled); }
@Override public SortedMultiset<E> descendingMultiset() { return new StandardDescendingMultiset() { @Override Iterator<Entry<E>> entryIterator() { return backingMultiset .descendingMultiset() .entrySet() .iterator(); } }; }