| /* TreeSet.java -- a class providing a TreeMap-backed SortedSet | |
| Copyright (C) 1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc. | |
| This file is part of GNU Classpath. | |
| GNU Classpath is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 2, or (at your option) | |
| any later version. | |
| GNU Classpath is distributed in the hope that it will be useful, but | |
| WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with GNU Classpath; see the file COPYING. If not, write to the | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
| 02110-1301 USA. | |
| Linking this library statically or dynamically with other modules is | |
| making a combined work based on this library. Thus, the terms and | |
| conditions of the GNU General Public License cover the whole | |
| combination. | |
| As a special exception, the copyright holders of this library give you | |
| permission to link this library with independent modules to produce an | |
| executable, regardless of the license terms of these independent | |
| modules, and to copy and distribute the resulting executable under | |
| terms of your choice, provided that you also meet, for each linked | |
| independent module, the terms and conditions of the license of that | |
| module. An independent module is a module which is not derived from | |
| or based on this library. If you modify this library, you may extend | |
| this exception to your version of the library, but you are not | |
| obligated to do so. If you do not wish to do so, delete this | |
| exception statement from your version. */ | |
| package java.util; | |
| import java.io.IOException; | |
| import java.io.ObjectInputStream; | |
| import java.io.ObjectOutputStream; | |
| import java.io.Serializable; | |
| /** | |
| * This class provides a TreeMap-backed implementation of the SortedSet | |
| * interface. The elements will be sorted according to their <i>natural | |
| * order</i>, or according to the provided <code>Comparator</code>.<p> | |
| * | |
| * Most operations are O(log n), but there is so much overhead that this | |
| * makes small sets expensive. Note that the ordering must be <i>consistent | |
| * with equals</i> to correctly implement the Set interface. If this | |
| * condition is violated, the set is still well-behaved, but you may have | |
| * suprising results when comparing it to other sets.<p> | |
| * | |
| * This implementation is not synchronized. If you need to share this between | |
| * multiple threads, do something like:<br> | |
| * <code>SortedSet s | |
| * = Collections.synchronizedSortedSet(new TreeSet(...));</code><p> | |
| * | |
| * The iterators are <i>fail-fast</i>, meaning that any structural | |
| * modification, except for <code>remove()</code> called on the iterator | |
| * itself, cause the iterator to throw a | |
| * <code>ConcurrentModificationException</code> rather than exhibit | |
| * non-deterministic behavior. | |
| * | |
| * @author Jon Zeppieri | |
| * @author Bryce McKinlay | |
| * @author Eric Blake (ebb9@email.byu.edu) | |
| * @author Tom Tromey (tromey@redhat.com) | |
| * @author Andrew John Hughes (gnu_andrew@member.fsf.org) | |
| * @see Collection | |
| * @see Set | |
| * @see HashSet | |
| * @see LinkedHashSet | |
| * @see Comparable | |
| * @see Comparator | |
| * @see Collections#synchronizedSortedSet(SortedSet) | |
| * @see TreeMap | |
| * @since 1.2 | |
| * @status updated to 1.6 | |
| */ | |
| public class TreeSet<T> extends AbstractSet<T> | |
| implements NavigableSet<T>, Cloneable, Serializable | |
| { | |
| /** | |
| * Compatible with JDK 1.2. | |
| */ | |
| private static final long serialVersionUID = -2479143000061671589L; | |
| /** | |
| * The NavigableMap which backs this Set. | |
| */ | |
| // Not final because of readObject. This will always be one of TreeMap or | |
| // TreeMap.SubMap, which both extend AbstractMap. | |
| private transient NavigableMap<T, String> map; | |
| /** | |
| * Construct a new TreeSet whose backing TreeMap using the "natural" | |
| * ordering of keys. Elements that are not mutually comparable will cause | |
| * ClassCastExceptions down the road. | |
| * | |
| * @see Comparable | |
| */ | |
| public TreeSet() | |
| { | |
| map = new TreeMap<T, String>(); | |
| } | |
| /** | |
| * Construct a new TreeSet whose backing TreeMap uses the supplied | |
| * Comparator. Elements that are not mutually comparable will cause | |
| * ClassCastExceptions down the road. | |
| * | |
| * @param comparator the Comparator this Set will use | |
| */ | |
| public TreeSet(Comparator<? super T> comparator) | |
| { | |
| map = new TreeMap<T, String>(comparator); | |
| } | |
| /** | |
| * Construct a new TreeSet whose backing TreeMap uses the "natural" | |
| * orering of the keys and which contains all of the elements in the | |
| * supplied Collection. This runs in n*log(n) time. | |
| * | |
| * @param collection the new Set will be initialized with all | |
| * of the elements in this Collection | |
| * @throws ClassCastException if the elements of the collection are not | |
| * comparable | |
| * @throws NullPointerException if the collection is null | |
| * @see Comparable | |
| */ | |
| public TreeSet(Collection<? extends T> collection) | |
| { | |
| map = new TreeMap<T, String>(); | |
| addAll(collection); | |
| } | |
| /** | |
| * Construct a new TreeSet, using the same key ordering as the supplied | |
| * SortedSet and containing all of the elements in the supplied SortedSet. | |
| * This constructor runs in linear time. | |
| * | |
| * @param sortedSet the new TreeSet will use this SortedSet's comparator | |
| * and will initialize itself with all its elements | |
| * @throws NullPointerException if sortedSet is null | |
| */ | |
| public TreeSet(SortedSet<T> sortedSet) | |
| { | |
| Iterator<T> itr; | |
| map = new TreeMap<T, String> | |
| ((Comparator<? super T>)sortedSet.comparator()); | |
| itr = ((SortedSet<T>) sortedSet).iterator(); | |
| ((TreeMap<T, String>) map).putKeysLinear(itr, sortedSet.size()); | |
| } | |
| /** | |
| * This private constructor is used to implement the subSet() calls around | |
| * a backing TreeMap.SubMap. | |
| * | |
| * @param backingMap the submap | |
| */ | |
| private TreeSet(NavigableMap<T,String> backingMap) | |
| { | |
| map = backingMap; | |
| } | |
| /** | |
| * Adds the spplied Object to the Set if it is not already in the Set; | |
| * returns true if the element is added, false otherwise. | |
| * | |
| * @param obj the Object to be added to this Set | |
| * @throws ClassCastException if the element cannot be compared with objects | |
| * already in the set | |
| */ | |
| public boolean add(T obj) | |
| { | |
| return map.put(obj, "") == null; | |
| } | |
| /** | |
| * Adds all of the elements in the supplied Collection to this TreeSet. | |
| * | |
| * @param c The collection to add | |
| * @return true if the Set is altered, false otherwise | |
| * @throws NullPointerException if c is null | |
| * @throws ClassCastException if an element in c cannot be compared with | |
| * objects already in the set | |
| */ | |
| public boolean addAll(Collection<? extends T> c) | |
| { | |
| boolean result = false; | |
| int pos = c.size(); | |
| Iterator<? extends T> itr = c.iterator(); | |
| while (--pos >= 0) | |
| result |= (map.put(itr.next(), "") == null); | |
| return result; | |
| } | |
| /** | |
| * Removes all elements in this Set. | |
| */ | |
| public void clear() | |
| { | |
| map.clear(); | |
| } | |
| /** | |
| * Returns a shallow copy of this Set. The elements are not cloned. | |
| * | |
| * @return the cloned set | |
| */ | |
| public Object clone() | |
| { | |
| TreeSet<T> copy = null; | |
| try | |
| { | |
| copy = (TreeSet<T>) super.clone(); | |
| // Map may be either TreeMap or TreeMap.SubMap, hence the ugly casts. | |
| copy.map = (NavigableMap<T, String>) ((AbstractMap<T, String>) map).clone(); | |
| } | |
| catch (CloneNotSupportedException x) | |
| { | |
| // Impossible result. | |
| } | |
| return copy; | |
| } | |
| /** | |
| * Returns this Set's comparator. | |
| * | |
| * @return the comparator, or null if the set uses natural ordering | |
| */ | |
| public Comparator<? super T> comparator() | |
| { | |
| return map.comparator(); | |
| } | |
| /** | |
| * Returns true if this Set contains the supplied Object, false otherwise. | |
| * | |
| * @param obj the Object to check for | |
| * @return true if it is in the set | |
| * @throws ClassCastException if obj cannot be compared with objects | |
| * already in the set | |
| */ | |
| public boolean contains(Object obj) | |
| { | |
| return map.containsKey(obj); | |
| } | |
| /** | |
| * Returns the first (by order) element in this Set. | |
| * | |
| * @return the first element | |
| * @throws NoSuchElementException if the set is empty | |
| */ | |
| public T first() | |
| { | |
| return map.firstKey(); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements less than | |
| * <code>to</code>. The returned set is backed by the original, so changes | |
| * in one appear in the other. The subset will throw an | |
| * {@link IllegalArgumentException} for any attempt to access or add an | |
| * element beyond the specified cutoff. The returned set does not include | |
| * the endpoint; if you want inclusion, pass the successor element or | |
| * call {@link #headSet(T,boolean)}. This call is equivalent to | |
| * <code>headSet(to, false)</code>. | |
| * | |
| * @param to the (exclusive) cutoff point | |
| * @return a view of the set less than the cutoff | |
| * @throws ClassCastException if <code>to</code> is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if to is null, but the comparator does not | |
| * tolerate null elements | |
| */ | |
| public SortedSet<T> headSet(T to) | |
| { | |
| return headSet(to, false); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements less than | |
| * (or equal to, if <code>inclusive</code> is true) <code>to</code>. | |
| * The returned set is backed by the original, so changes | |
| * in one appear in the other. The subset will throw an | |
| * {@link IllegalArgumentException} for any attempt to access or add an | |
| * element beyond the specified cutoff. | |
| * | |
| * @param to the cutoff point | |
| * @param inclusive true if <code>to</code> should be included. | |
| * @return a view of the set for the specified range. | |
| * @throws ClassCastException if <code>to</code> is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if to is null, but the comparator does not | |
| * tolerate null elements | |
| */ | |
| public NavigableSet<T> headSet(T to, boolean inclusive) | |
| { | |
| return new TreeSet<T>(map.headMap(to, inclusive)); | |
| } | |
| /** | |
| * Returns true if this Set has size 0, false otherwise. | |
| * | |
| * @return true if the set is empty | |
| */ | |
| public boolean isEmpty() | |
| { | |
| return map.isEmpty(); | |
| } | |
| /** | |
| * Returns in Iterator over the elements in this TreeSet, which traverses | |
| * in ascending order. | |
| * | |
| * @return an iterator | |
| */ | |
| public Iterator<T> iterator() | |
| { | |
| return map.keySet().iterator(); | |
| } | |
| /** | |
| * Returns the last (by order) element in this Set. | |
| * | |
| * @return the last element | |
| * @throws NoSuchElementException if the set is empty | |
| */ | |
| public T last() | |
| { | |
| return map.lastKey(); | |
| } | |
| /** | |
| * If the supplied Object is in this Set, it is removed, and true is | |
| * returned; otherwise, false is returned. | |
| * | |
| * @param obj the Object to remove from this Set | |
| * @return true if the set was modified | |
| * @throws ClassCastException if obj cannot be compared to set elements | |
| */ | |
| public boolean remove(Object obj) | |
| { | |
| return map.remove(obj) != null; | |
| } | |
| /** | |
| * Returns the number of elements in this Set | |
| * | |
| * @return the set size | |
| */ | |
| public int size() | |
| { | |
| return map.size(); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements greater or equal to | |
| * <code>from</code> and less than <code>to</code> (a half-open interval). | |
| * The returned set is backed by the original, so changes in one appear in | |
| * the other. The subset will throw an {@link IllegalArgumentException} | |
| * for any attempt to access or add an element beyond the specified cutoffs. | |
| * The returned set includes the low endpoint but not the high; if you want | |
| * to reverse this behavior on either end, pass in the successor element | |
| * or call {@link #subSet(T,boolean,T,boolean)}. This is equivalent to | |
| * calling <code>subSet(from,true,to,false)</code>. | |
| * | |
| * @param from the (inclusive) low cutoff point | |
| * @param to the (exclusive) high cutoff point | |
| * @return a view of the set between the cutoffs | |
| * @throws ClassCastException if either cutoff is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if from or to is null, but the comparator | |
| * does not tolerate null elements | |
| * @throws IllegalArgumentException if from is greater than to | |
| */ | |
| public SortedSet<T> subSet(T from, T to) | |
| { | |
| return subSet(from, true, to, false); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements greater than (or equal to, | |
| * if <code>fromInclusive</code> is true</code> <code>from</code> and less than | |
| * (or equal to, if <code>toInclusive</code> is true) <code>to</code>. | |
| * The returned set is backed by the original, so changes in one appear in | |
| * the other. The subset will throw an {@link IllegalArgumentException} | |
| * for any attempt to access or add an element beyond the specified cutoffs. | |
| * | |
| * @param from the low cutoff point | |
| * @param fromInclusive true if <code>from</code> should be included. | |
| * @param to the high cutoff point | |
| * @param toInclusive true if <code>to</code> should be included. | |
| * @return a view of the set for the specified range. | |
| * @throws ClassCastException if either cutoff is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if from or to is null, but the comparator | |
| * does not tolerate null elements | |
| * @throws IllegalArgumentException if from is greater than to | |
| */ | |
| public NavigableSet<T> subSet(T from, boolean fromInclusive, | |
| T to, boolean toInclusive) | |
| { | |
| return new TreeSet<T>(map.subMap(from, fromInclusive, | |
| to, toInclusive)); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements greater or equal to | |
| * <code>from</code>. The returned set is backed by the original, so | |
| * changes in one appear in the other. The subset will throw an | |
| * {@link IllegalArgumentException} for any attempt to access or add an | |
| * element beyond the specified cutoff. The returned set includes the | |
| * endpoint; if you want to exclude it, pass in the successor element | |
| * or call {@link #tailSet(T,boolean)}. This is equivalent to calling | |
| * <code>tailSet(from, true)</code>. | |
| * | |
| * @param from the (inclusive) low cutoff point | |
| * @return a view of the set above the cutoff | |
| * @throws ClassCastException if <code>from</code> is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if from is null, but the comparator | |
| * does not tolerate null elements | |
| */ | |
| public SortedSet<T> tailSet(T from) | |
| { | |
| return tailSet(from, true); | |
| } | |
| /** | |
| * Returns a view of this Set including all elements greater (or equal to, | |
| * if <code>inclusive</code> is true) <code>from</code>. The returned set | |
| * is backed by the original, so changes in one appear in the other. The | |
| * subset will throw an {@link IllegalArgumentException} for any attempt | |
| * to access or add an element beyond the specified cutoff. | |
| * | |
| * @param from the low cutoff point. | |
| * @param inclusive true if <code>from</code> should be included. | |
| * @return a view of the set for the specified range. | |
| * @throws ClassCastException if <code>from</code> is not compatible with | |
| * the comparator (or is not Comparable, for natural ordering) | |
| * @throws NullPointerException if from is null, but the comparator | |
| * does not tolerate null elements | |
| */ | |
| public NavigableSet<T> tailSet(T from, boolean inclusive) | |
| { | |
| return new TreeSet<T>(map.tailMap(from, inclusive)); | |
| } | |
| /** | |
| * Serializes this object to the given stream. | |
| * | |
| * @param s the stream to write to | |
| * @throws IOException if the underlying stream fails | |
| * @serialData the <i>comparator</i> (Object), followed by the set size | |
| * (int), the the elements in sorted order (Object) | |
| */ | |
| private void writeObject(ObjectOutputStream s) throws IOException | |
| { | |
| s.defaultWriteObject(); | |
| Iterator<T> itr = map.keySet().iterator(); | |
| int pos = map.size(); | |
| s.writeObject(map.comparator()); | |
| s.writeInt(pos); | |
| while (--pos >= 0) | |
| s.writeObject(itr.next()); | |
| } | |
| /** | |
| * Deserializes this object from the given stream. | |
| * | |
| * @param s the stream to read from | |
| * @throws ClassNotFoundException if the underlying stream fails | |
| * @throws IOException if the underlying stream fails | |
| * @serialData the <i>comparator</i> (Object), followed by the set size | |
| * (int), the the elements in sorted order (Object) | |
| */ | |
| private void readObject(ObjectInputStream s) | |
| throws IOException, ClassNotFoundException | |
| { | |
| s.defaultReadObject(); | |
| Comparator<? super T> comparator = (Comparator<? super T>) s.readObject(); | |
| int size = s.readInt(); | |
| map = new TreeMap<T, String>(comparator); | |
| ((TreeMap<T, String>) map).putFromObjStream(s, size, false); | |
| } | |
| /** | |
| * Returns the least or lowest element in the set greater than or | |
| * equal to the given element, or <code>null</code> if there is | |
| * no such element. | |
| * | |
| * @param e the element relative to the returned element. | |
| * @return the least element greater than or equal | |
| * to the given element, or <code>null</code> if there is | |
| * no such element. | |
| * @throws ClassCastException if the specified element can not | |
| * be compared with those in the map. | |
| * @throws NullPointerException if the element is <code>null</code> | |
| * and this set either uses natural | |
| * ordering or a comparator that does | |
| * not permit null elements. | |
| * @since 1.6 | |
| */ | |
| public T ceiling(T e) | |
| { | |
| return map.ceilingKey(e); | |
| } | |
| /** | |
| * Returns an iterator over the elements of this set in descending | |
| * order. This is equivalent to calling | |
| * <code>descendingSet().iterator()</code>. | |
| * | |
| * @return an iterator over the elements in descending order. | |
| * @since 1.6 | |
| */ | |
| public Iterator<T> descendingIterator() | |
| { | |
| return descendingSet().iterator(); | |
| } | |
| /** | |
| * Returns a view of the set in reverse order. The descending set | |
| * is backed by the original set, so that changes affect both sets. | |
| * Any changes occurring to either set while an iteration is taking | |
| * place (with the exception of a {@link Iterator#remove()} operation) | |
| * result in undefined behaviour from the iteration. The ordering | |
| * of the descending set is the same as for a set with a | |
| * {@link Comparator} given by {@link Collections#reverseOrder()}, | |
| * and calling {@link #descendingSet()} on the descending set itself | |
| * results in a view equivalent to the original set. | |
| * | |
| * @return a reverse order view of the set. | |
| * @since 1.6 | |
| */ | |
| public NavigableSet<T> descendingSet() | |
| { | |
| return map.descendingKeySet(); | |
| } | |
| /** | |
| * Returns the greatest or highest element in the set less than or | |
| * equal to the given element, or <code>null</code> if there is | |
| * no such element. | |
| * | |
| * @param e the element relative to the returned element. | |
| * @return the greatest element less than or equal | |
| * to the given element, or <code>null</code> if there is | |
| * no such element. | |
| * @throws ClassCastException if the specified element can not | |
| * be compared with those in the map. | |
| * @throws NullPointerException if the element is <code>null</code> | |
| * and this set either uses natural | |
| * ordering or a comparator that does | |
| * not permit null elements. | |
| * @since 1.6 | |
| */ | |
| public T floor(T e) | |
| { | |
| return map.floorKey(e); | |
| } | |
| /** | |
| * Returns the least or lowest element in the set strictly greater | |
| * than the given element, or <code>null</code> if there is | |
| * no such element. | |
| * | |
| * @param e the element relative to the returned element. | |
| * @return the least element greater than | |
| * the given element, or <code>null</code> if there is | |
| * no such element. | |
| * @throws ClassCastException if the specified element can not | |
| * be compared with those in the map. | |
| * @throws NullPointerException if the element is <code>null</code> | |
| * and this set either uses natural | |
| * ordering or a comparator that does | |
| * not permit null elements. | |
| * @since 1.6 | |
| */ | |
| public T higher(T e) | |
| { | |
| return map.higherKey(e); | |
| } | |
| /** | |
| * Returns the greatest or highest element in the set strictly less | |
| * than the given element, or <code>null</code> if there is | |
| * no such element. | |
| * | |
| * @param e the element relative to the returned element. | |
| * @return the greatest element less than | |
| * the given element, or <code>null</code> if there is | |
| * no such element. | |
| * @throws ClassCastException if the specified element can not | |
| * be compared with those in the map. | |
| * @throws NullPointerException if the element is <code>null</code> | |
| * and this set either uses natural | |
| * ordering or a comparator that does | |
| * not permit null elements. | |
| * @since 1.6 | |
| */ | |
| public T lower(T e) | |
| { | |
| return map.lowerKey(e); | |
| } | |
| /** | |
| * Removes and returns the least or lowest element in the set, | |
| * or <code>null</code> if the map is empty. | |
| * | |
| * @return the removed first element, or <code>null</code> if the | |
| * map is empty. | |
| * @since 1.6 | |
| */ | |
| public T pollFirst() | |
| { | |
| return map.pollFirstEntry().getKey(); | |
| } | |
| /** | |
| * Removes and returns the greatest or highest element in the set, | |
| * or <code>null</code> if the map is empty. | |
| * | |
| * @return the removed last element, or <code>null</code> if the | |
| * map is empty. | |
| * @since 1.6 | |
| */ | |
| public T pollLast() | |
| { | |
| return map.pollLastEntry().getKey(); | |
| } | |
| } |