1 /* 2 * Copyright (C) 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.collect; 18 19 import com.google.common.annotations.GwtCompatible; 20 21 import java.io.IOException; 22 import java.io.ObjectInputStream; 23 import java.io.ObjectOutputStream; 24 import java.util.Comparator; 25 import java.util.Set; 26 import java.util.SortedMap; 27 import java.util.SortedSet; 28 import java.util.TreeMap; 29 import java.util.Collection; 30 import java.util.concurrent.atomic.AtomicInteger; 31 32 import javax.annotation.Nullable; 33 34 /** 35 * A multiset which maintains the ordering of its elements, according to either 36 * their natural order or an explicit {@link Comparator}. In all cases, this 37 * implementation uses {@link Comparable#compareTo} or {@link 38 * Comparator#compare} instead of {@link Object#equals} to determine 39 * equivalence of instances. 40 * 41 * <p><b>Warning:</b> The comparison must be <i>consistent with equals</i> as 42 * explained by the {@link Comparable} class specification. Otherwise, the 43 * resulting multiset will violate the {@link Collection} contract, which it is 44 * specified in terms of {@link Object#equals}. 45 * 46 * @author Neal Kanodia 47 * @author Jared Levy 48 * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library) 49 */ 50 @GwtCompatible 51 @SuppressWarnings("serial") // we're overriding default serialization 52 public final class TreeMultiset<E> extends AbstractMapBasedMultiset<E> { 53 54 /** 55 * Creates a new, empty multiset, sorted according to the elements' natural 56 * order. All elements inserted into the multiset must implement the 57 * {@code Comparable} interface. Furthermore, all such elements must be 58 * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a 59 * {@code ClassCastException} for any elements {@code e1} and {@code e2} in 60 * the multiset. If the user attempts to add an element to the multiset that 61 * violates this constraint (for example, the user attempts to add a string 62 * element to a set whose elements are integers), the {@code add(Object)} 63 * call will throw a {@code ClassCastException}. 64 * 65 * <p>The type specification is {@code <E extends Comparable>}, instead of the 66 * more specific {@code <E extends Comparable<? super E>>}, to support 67 * classes defined without generics. 68 */ 69 @SuppressWarnings("unchecked") // eclipse doesn't like the raw Comparable create()70 public static <E extends Comparable> TreeMultiset<E> create() { 71 return new TreeMultiset<E>(); 72 } 73 74 /** 75 * Creates a new, empty multiset, sorted according to the specified 76 * comparator. All elements inserted into the multiset must be <i>mutually 77 * comparable</i> by the specified comparator: {@code comparator.compare(e1, 78 * e2)} must not throw a {@code ClassCastException} for any elements {@code 79 * e1} and {@code e2} in the multiset. If the user attempts to add an element 80 * to the multiset that violates this constraint, the {@code add(Object)} call 81 * will throw a {@code ClassCastException}. 82 * 83 * @param comparator the comparator that will be used to sort this multiset. A 84 * null value indicates that the elements' <i>natural ordering</i> should 85 * be used. 86 */ create(Comparator<? super E> comparator)87 public static <E> TreeMultiset<E> create(Comparator<? super E> comparator) { 88 return new TreeMultiset<E>(comparator); 89 } 90 91 /** 92 * Creates an empty multiset containing the given initial elements, sorted 93 * according to the elements' natural order. 94 * 95 * <p>The type specification is {@code <E extends Comparable>}, instead of the 96 * more specific {@code <E extends Comparable<? super E>>}, to support 97 * classes defined without generics. 98 */ 99 @SuppressWarnings("unchecked") // eclipse doesn't like the raw Comparable create( Iterable<? extends E> elements)100 public static <E extends Comparable> TreeMultiset<E> create( 101 Iterable<? extends E> elements) { 102 TreeMultiset<E> multiset = create(); 103 Iterables.addAll(multiset, elements); 104 return multiset; 105 } 106 TreeMultiset()107 private TreeMultiset() { 108 super(new TreeMap<E, AtomicInteger>()); 109 } 110 TreeMultiset(Comparator<? super E> comparator)111 private TreeMultiset(Comparator<? super E> comparator) { 112 super(new TreeMap<E, AtomicInteger>(comparator)); 113 } 114 115 /** 116 * {@inheritDoc} 117 * 118 * <p>In {@code TreeMultiset}, the return type of this method is narrowed 119 * from {@link Set} to {@link SortedSet}. 120 */ elementSet()121 @Override public SortedSet<E> elementSet() { 122 return (SortedSet<E>) super.elementSet(); 123 } 124 count(@ullable Object element)125 @Override public int count(@Nullable Object element) { 126 try { 127 return super.count(element); 128 } catch (NullPointerException e) { 129 return 0; 130 } catch (ClassCastException e) { 131 return 0; 132 } 133 } 134 createElementSet()135 @Override Set<E> createElementSet() { 136 return new SortedMapBasedElementSet( 137 (SortedMap<E, AtomicInteger>) backingMap()); 138 } 139 140 private class SortedMapBasedElementSet extends MapBasedElementSet 141 implements SortedSet<E> { 142 SortedMapBasedElementSet(SortedMap<E, AtomicInteger> map)143 SortedMapBasedElementSet(SortedMap<E, AtomicInteger> map) { 144 super(map); 145 } 146 sortedMap()147 SortedMap<E, AtomicInteger> sortedMap() { 148 return (SortedMap<E, AtomicInteger>) getMap(); 149 } 150 comparator()151 public Comparator<? super E> comparator() { 152 return sortedMap().comparator(); 153 } 154 first()155 public E first() { 156 return sortedMap().firstKey(); 157 } 158 last()159 public E last() { 160 return sortedMap().lastKey(); 161 } 162 headSet(E toElement)163 public SortedSet<E> headSet(E toElement) { 164 return new SortedMapBasedElementSet(sortedMap().headMap(toElement)); 165 } 166 subSet(E fromElement, E toElement)167 public SortedSet<E> subSet(E fromElement, E toElement) { 168 return new SortedMapBasedElementSet( 169 sortedMap().subMap(fromElement, toElement)); 170 } 171 tailSet(E fromElement)172 public SortedSet<E> tailSet(E fromElement) { 173 return new SortedMapBasedElementSet(sortedMap().tailMap(fromElement)); 174 } 175 remove(Object element)176 @Override public boolean remove(Object element) { 177 try { 178 return super.remove(element); 179 } catch (NullPointerException e) { 180 return false; 181 } catch (ClassCastException e) { 182 return false; 183 } 184 } 185 } 186 187 /* 188 * TODO: Decide whether entrySet() should return entries with an equals() 189 * method that calls the comparator to compare the two keys. If that change 190 * is made, AbstractMultiset.equals() can simply check whether two multisets 191 * have equal entry sets. 192 */ 193 194 /** 195 * @serialData the comparator, the number of distinct elements, the first 196 * element, its count, the second element, its count, and so on 197 */ writeObject(ObjectOutputStream stream)198 private void writeObject(ObjectOutputStream stream) throws IOException { 199 stream.defaultWriteObject(); 200 stream.writeObject(elementSet().comparator()); 201 Serialization.writeMultiset(this, stream); 202 } 203 readObject(ObjectInputStream stream)204 private void readObject(ObjectInputStream stream) 205 throws IOException, ClassNotFoundException { 206 stream.defaultReadObject(); 207 @SuppressWarnings("unchecked") // reading data stored by writeObject 208 Comparator<? super E> comparator 209 = (Comparator<? super E>) stream.readObject(); 210 setBackingMap(new TreeMap<E, AtomicInteger>(comparator)); 211 Serialization.populateMultiset(this, stream); 212 } 213 214 private static final long serialVersionUID = 0; 215 } 216