/* * Copyright (C) 2011 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 com.google.common.annotations.GwtCompatible; import com.google.common.collect.Multiset.Entry; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import java.util.SortedSet; /** * Provides static utility methods for creating and working with * {@link SortedMultiset} instances. * * @author Louis Wasserman */ @GwtCompatible final class SortedMultisets { private SortedMultisets() { } /** * A skeleton implementation for {@link SortedMultiset#elementSet}. */ static abstract class ElementSet extends Multisets.ElementSet implements SortedSet { @Override abstract SortedMultiset multiset(); @Override public Comparator comparator() { return multiset().comparator(); } @Override public SortedSet subSet(E fromElement, E toElement) { return multiset().subMultiset(fromElement, BoundType.CLOSED, toElement, BoundType.OPEN).elementSet(); } @Override public SortedSet headSet(E toElement) { return multiset().headMultiset(toElement, BoundType.OPEN).elementSet(); } @Override public SortedSet tailSet(E fromElement) { return multiset().tailMultiset(fromElement, BoundType.CLOSED) .elementSet(); } @Override public E first() { return getElementOrThrow(multiset().firstEntry()); } @Override public E last() { return getElementOrThrow(multiset().lastEntry()); } } private static E getElementOrThrow(Entry entry) { if (entry == null) { throw new NoSuchElementException(); } return entry.getElement(); } /** * A skeleton implementation of a descending multiset. Only needs * {@code forwardMultiset()} and {@code entryIterator()}. */ static abstract class DescendingMultiset extends ForwardingMultiset implements SortedMultiset { abstract SortedMultiset forwardMultiset(); private transient Comparator comparator; @Override public Comparator comparator() { Comparator result = comparator; if (result == null) { return comparator = Ordering.from(forwardMultiset().comparator()).reverse(); } return result; } private transient SortedSet elementSet; @Override public SortedSet elementSet() { SortedSet result = elementSet; if (result == null) { return elementSet = new SortedMultisets.ElementSet() { @Override SortedMultiset multiset() { return DescendingMultiset.this; } }; } return result; } @Override public Entry pollFirstEntry() { return forwardMultiset().pollLastEntry(); } @Override public Entry pollLastEntry() { return forwardMultiset().pollFirstEntry(); } @Override public SortedMultiset headMultiset(E toElement, BoundType boundType) { return forwardMultiset().tailMultiset(toElement, boundType) .descendingMultiset(); } @Override public SortedMultiset subMultiset(E fromElement, BoundType fromBoundType, E toElement, BoundType toBoundType) { return forwardMultiset().subMultiset(toElement, toBoundType, fromElement, fromBoundType).descendingMultiset(); } @Override public SortedMultiset tailMultiset(E fromElement, BoundType boundType) { return forwardMultiset().headMultiset(fromElement, boundType) .descendingMultiset(); } @Override protected Multiset delegate() { return forwardMultiset(); } @Override public SortedMultiset descendingMultiset() { return forwardMultiset(); } @Override public Entry firstEntry() { return forwardMultiset().lastEntry(); } @Override public Entry lastEntry() { return forwardMultiset().firstEntry(); } abstract Iterator> entryIterator(); private transient Set> entrySet; @Override public Set> entrySet() { Set> result = entrySet; return (result == null) ? entrySet = createEntrySet() : result; } Set> createEntrySet() { return new Multisets.EntrySet() { @Override Multiset multiset() { return DescendingMultiset.this; } @Override public Iterator> iterator() { return entryIterator(); } @Override public int size() { return forwardMultiset().entrySet().size(); } }; } @Override public Iterator iterator() { return Multisets.iteratorImpl(this); } @Override public Object[] toArray() { return standardToArray(); } @Override public T[] toArray(T[] array) { return standardToArray(array); } @Override public String toString() { return entrySet().toString(); } } }