1. /*
  2. * @(#)TreeSet.java 1.26 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.util;
  8. /**
  9. * This class implements the <tt>Set</tt> interface, backed by a
  10. * <tt>TreeMap</tt> instance. This class guarantees that the sorted set will
  11. * be in ascending element order, sorted according to the <i>natural order</i>
  12. * of the elements (see <tt>Comparable</tt>), or by the comparator provided at
  13. * set creation time, depending on which constructor is used.<p>
  14. *
  15. * This implementation provides guaranteed log(n) time cost for the basic
  16. * operations (<tt>add</tt>, <tt>remove</tt> and <tt>contains</tt>).<p>
  17. *
  18. * Note that the ordering maintained by a set (whether or not an explicit
  19. * comparator is provided) must be <i>consistent with equals</i> if it is to
  20. * correctly implement the <tt>Set</tt> interface. (See <tt>Comparable</tt>
  21. * or <tt>Comparator</tt> for a precise definition of <i>consistent with
  22. * equals</i>.) This is so because the <tt>Set</tt> interface is defined in
  23. * terms of the <tt>equals</tt> operation, but a <tt>TreeSet</tt> instance
  24. * performs all key comparisons using its <tt>compareTo</tt> (or
  25. * <tt>compare</tt>) method, so two keys that are deemed equal by this method
  26. * are, from the standpoint of the set, equal. The behavior of a set
  27. * <i>is</i> well-defined even if its ordering is inconsistent with equals; it
  28. * just fails to obey the general contract of the <tt>Set</tt> interface.<p>
  29. *
  30. * <b>Note that this implementation is not synchronized.</b> If multiple
  31. * threads access a set concurrently, and at least one of the threads modifies
  32. * the set, it <i>must</i> be synchronized externally. This is typically
  33. * accomplished by synchronizing on some object that naturally encapsulates
  34. * the set. If no such object exists, the set should be "wrapped" using the
  35. * <tt>Collections.synchronizedSet</tt> method. This is best done at creation
  36. * time, to prevent accidental unsynchronized access to the set: <pre>
  37. * SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));
  38. * </pre><p>
  39. *
  40. * The Iterators returned by this class's <tt>iterator</tt> method are
  41. * <i>fail-fast</i>: if the set is modified at any time after the iterator is
  42. * created, in any way except through the iterator's own <tt>remove</tt>
  43. * method, the iterator will throw a <tt>ConcurrentModificationException</tt>.
  44. * Thus, in the face of concurrent modification, the iterator fails quickly
  45. * and cleanly, rather than risking arbitrary, non-deterministic behavior at
  46. * an undetermined time in the future.
  47. *
  48. * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  49. * as it is, generally speaking, impossible to make any hard guarantees in the
  50. * presence of unsynchronized concurrent modification. Fail-fast iterators
  51. * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
  52. * Therefore, it would be wrong to write a program that depended on this
  53. * exception for its correctness: <i>the fail-fast behavior of iterators
  54. * should be used only to detect bugs.</i><p>
  55. *
  56. * This class is a member of the
  57. * <a href="{@docRoot}/../guide/collections/index.html">
  58. * Java Collections Framework</a>.
  59. *
  60. * @author Josh Bloch
  61. * @version 1.26, 01/23/03
  62. * @see Collection
  63. * @see Set
  64. * @see HashSet
  65. * @see Comparable
  66. * @see Comparator
  67. * @see Collections#synchronizedSortedSet(SortedSet)
  68. * @see TreeMap
  69. * @since 1.2
  70. */
  71. public class TreeSet extends AbstractSet
  72. implements SortedSet, Cloneable, java.io.Serializable
  73. {
  74. private transient SortedMap m; // The backing Map
  75. private transient Set keySet; // The keySet view of the backing Map
  76. // Dummy value to associate with an Object in the backing Map
  77. private static final Object PRESENT = new Object();
  78. /**
  79. * Constructs a set backed by the specified sorted map.
  80. */
  81. private TreeSet(SortedMap m) {
  82. this.m = m;
  83. keySet = m.keySet();
  84. }
  85. /**
  86. * Constructs a new, empty set, sorted according to the elements' natural
  87. * order. All elements inserted into the set must implement the
  88. * <tt>Comparable</tt> interface. Furthermore, all such elements must be
  89. * <i>mutually comparable</i>: <tt>e1.compareTo(e2)</tt> must not throw a
  90. * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
  91. * <tt>e2</tt> in the set. If the user attempts to add an element to the
  92. * set that violates this constraint (for example, the user attempts to
  93. * add a string element to a set whose elements are integers), the
  94. * <tt>add(Object)</tt> call will throw a <tt>ClassCastException</tt>.
  95. *
  96. * @see Comparable
  97. */
  98. public TreeSet() {
  99. this(new TreeMap());
  100. }
  101. /**
  102. * Constructs a new, empty set, sorted according to the specified
  103. * comparator. All elements inserted into the set must be <i>mutually
  104. * comparable</i> by the specified comparator: <tt>comparator.compare(e1,
  105. * e2)</tt> must not throw a <tt>ClassCastException</tt> for any elements
  106. * <tt>e1</tt> and <tt>e2</tt> in the set. If the user attempts to add
  107. * an element to the set that violates this constraint, the
  108. * <tt>add(Object)</tt> call will throw a <tt>ClassCastException</tt>.
  109. *
  110. * @param c the comparator that will be used to sort this set. A
  111. * <tt>null</tt> value indicates that the elements' <i>natural
  112. * ordering</i> should be used.
  113. */
  114. public TreeSet(Comparator c) {
  115. this(new TreeMap(c));
  116. }
  117. /**
  118. * Constructs a new set containing the elements in the specified
  119. * collection, sorted according to the elements' <i>natural order</i>.
  120. * All keys inserted into the set must implement the <tt>Comparable</tt>
  121. * interface. Furthermore, all such keys must be <i>mutually
  122. * comparable</i>: <tt>k1.compareTo(k2)</tt> must not throw a
  123. * <tt>ClassCastException</tt> for any elements <tt>k1</tt> and
  124. * <tt>k2</tt> in the set.
  125. *
  126. * @param c The elements that will comprise the new set.
  127. *
  128. * @throws ClassCastException if the keys in the specified collection are
  129. * not comparable, or are not mutually comparable.
  130. * @throws NullPointerException if the specified collection is null.
  131. */
  132. public TreeSet(Collection c) {
  133. this();
  134. addAll(c);
  135. }
  136. /**
  137. * Constructs a new set containing the same elements as the specified
  138. * sorted set, sorted according to the same ordering.
  139. *
  140. * @param s sorted set whose elements will comprise the new set.
  141. * @throws NullPointerException if the specified sorted set is null.
  142. */
  143. public TreeSet(SortedSet s) {
  144. this(s.comparator());
  145. addAll(s);
  146. }
  147. /**
  148. * Returns an iterator over the elements in this set. The elements
  149. * are returned in ascending order.
  150. *
  151. * @return an iterator over the elements in this set.
  152. */
  153. public Iterator iterator() {
  154. return keySet.iterator();
  155. }
  156. /**
  157. * Returns the number of elements in this set (its cardinality).
  158. *
  159. * @return the number of elements in this set (its cardinality).
  160. */
  161. public int size() {
  162. return m.size();
  163. }
  164. /**
  165. * Returns <tt>true</tt> if this set contains no elements.
  166. *
  167. * @return <tt>true</tt> if this set contains no elements.
  168. */
  169. public boolean isEmpty() {
  170. return m.isEmpty();
  171. }
  172. /**
  173. * Returns <tt>true</tt> if this set contains the specified element.
  174. *
  175. * @param o the object to be checked for containment in this set.
  176. * @return <tt>true</tt> if this set contains the specified element.
  177. *
  178. * @throws ClassCastException if the specified object cannot be compared
  179. * with the elements currently in the set.
  180. */
  181. public boolean contains(Object o) {
  182. return m.containsKey(o);
  183. }
  184. /**
  185. * Adds the specified element to this set if it is not already present.
  186. *
  187. * @param o element to be added to this set.
  188. * @return <tt>true</tt> if the set did not already contain the specified
  189. * element.
  190. *
  191. * @throws ClassCastException if the specified object cannot be compared
  192. * with the elements currently in the set.
  193. */
  194. public boolean add(Object o) {
  195. return m.put(o, PRESENT)==null;
  196. }
  197. /**
  198. * Removes the specified element from this set if it is present.
  199. *
  200. * @param o object to be removed from this set, if present.
  201. * @return <tt>true</tt> if the set contained the specified element.
  202. *
  203. * @throws ClassCastException if the specified object cannot be compared
  204. * with the elements currently in the set.
  205. */
  206. public boolean remove(Object o) {
  207. return m.remove(o)==PRESENT;
  208. }
  209. /**
  210. * Removes all of the elements from this set.
  211. */
  212. public void clear() {
  213. m.clear();
  214. }
  215. /**
  216. * Adds all of the elements in the specified collection to this set.
  217. *
  218. * @param c elements to be added
  219. * @return <tt>true</tt> if this set changed as a result of the call.
  220. *
  221. * @throws ClassCastException if the elements provided cannot be compared
  222. * with the elements currently in the set.
  223. * @throws NullPointerException of the specified collection is null.
  224. */
  225. public boolean addAll(Collection c) {
  226. // Use linear-time version if applicable
  227. if (m.size()==0 && c.size() > 0 && c instanceof SortedSet &&
  228. m instanceof TreeMap) {
  229. SortedSet set = (SortedSet)c;
  230. TreeMap map = (TreeMap)m;
  231. Comparator cc = set.comparator();
  232. Comparator mc = map.comparator();
  233. if (cc==mc || (cc != null && cc.equals(mc))) {
  234. map.addAllForTreeSet(set, PRESENT);
  235. return true;
  236. }
  237. }
  238. return super.addAll(c);
  239. }
  240. /**
  241. * Returns a view of the portion of this set whose elements range from
  242. * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>, exclusive. (If
  243. * <tt>fromElement</tt> and <tt>toElement</tt> are equal, the returned
  244. * sorted set is empty.) The returned sorted set is backed by this set,
  245. * so changes in the returned sorted set are reflected in this set, and
  246. * vice-versa. The returned sorted set supports all optional Set
  247. * operations.<p>
  248. *
  249. * The sorted set returned by this method will throw an
  250. * <tt>IllegalArgumentException</tt> if the user attempts to insert an
  251. * element outside the specified range.<p>
  252. *
  253. * Note: this method always returns a <i>half-open range</i> (which
  254. * includes its low endpoint but not its high endpoint). If you need a
  255. * <i>closed range</i> (which includes both endpoints), and the element
  256. * type allows for calculation of the successor of a specified value,
  257. * merely request the subrange from <tt>lowEndpoint</tt> to
  258. * <tt>successor(highEndpoint)</tt>. For example, suppose that <tt>s</tt>
  259. * is a sorted set of strings. The following idiom obtains a view
  260. * containing all of the strings in <tt>s</tt> from <tt>low</tt> to
  261. * <tt>high</tt>, inclusive: <pre>
  262. * SortedSet sub = s.subSet(low, high+"\0");
  263. * </pre>
  264. *
  265. * A similar technique can be used to generate an <i>open range</i> (which
  266. * contains neither endpoint). The following idiom obtains a view
  267. * containing all of the strings in <tt>s</tt> from <tt>low</tt> to
  268. * <tt>high</tt>, exclusive: <pre>
  269. * SortedSet sub = s.subSet(low+"\0", high);
  270. * </pre>
  271. *
  272. * @param fromElement low endpoint (inclusive) of the subSet.
  273. * @param toElement high endpoint (exclusive) of the subSet.
  274. * @return a view of the portion of this set whose elements range from
  275. * <tt>fromElement</tt>, inclusive, to <tt>toElement</tt>,
  276. * exclusive.
  277. * @throws ClassCastException if <tt>fromElement</tt> and
  278. * <tt>toElement</tt> cannot be compared to one another using
  279. * this set's comparator (or, if the set has no comparator,
  280. * using natural ordering).
  281. * @throws IllegalArgumentException if <tt>fromElement</tt> is greater than
  282. * <tt>toElement</tt>.
  283. * @throws NullPointerException if <tt>fromElement</tt> or
  284. * <tt>toElement</tt> is <tt>null</tt> and this set uses natural
  285. * order, or its comparator does not tolerate <tt>null</tt>
  286. * elements.
  287. */
  288. public SortedSet subSet(Object fromElement, Object toElement) {
  289. return new TreeSet(m.subMap(fromElement, toElement));
  290. }
  291. /**
  292. * Returns a view of the portion of this set whose elements are strictly
  293. * less than <tt>toElement</tt>. The returned sorted set is backed by
  294. * this set, so changes in the returned sorted set are reflected in this
  295. * set, and vice-versa. The returned sorted set supports all optional set
  296. * operations.<p>
  297. *
  298. * The sorted set returned by this method will throw an
  299. * <tt>IllegalArgumentException</tt> if the user attempts to insert an
  300. * element greater than or equal to <tt>toElement</tt>.<p>
  301. *
  302. * Note: this method always returns a view that does not contain its
  303. * (high) endpoint. If you need a view that does contain this endpoint,
  304. * and the element type allows for calculation of the successor of a
  305. * specified value, merely request a headSet bounded by
  306. * <tt>successor(highEndpoint)</tt>. For example, suppose that <tt>s</tt>
  307. * is a sorted set of strings. The following idiom obtains a view
  308. * containing all of the strings in <tt>s</tt> that are less than or equal
  309. * to <tt>high</tt>: <pre> SortedSet head = s.headSet(high+"\0");</pre>
  310. *
  311. * @param toElement high endpoint (exclusive) of the headSet.
  312. * @return a view of the portion of this set whose elements are strictly
  313. * less than toElement.
  314. * @throws ClassCastException if <tt>toElement</tt> is not compatible
  315. * with this set's comparator (or, if the set has no comparator,
  316. * if <tt>toElement</tt> does not implement <tt>Comparable</tt>).
  317. * @throws IllegalArgumentException if this set is itself a subSet,
  318. * headSet, or tailSet, and <tt>toElement</tt> is not within the
  319. * specified range of the subSet, headSet, or tailSet.
  320. * @throws NullPointerException if <tt>toElement</tt> is <tt>null</tt> and
  321. * this set uses natural ordering, or its comparator does
  322. * not tolerate <tt>null</tt> elements.
  323. */
  324. public SortedSet headSet(Object toElement) {
  325. return new TreeSet(m.headMap(toElement));
  326. }
  327. /**
  328. * Returns a view of the portion of this set whose elements are
  329. * greater than or equal to <tt>fromElement</tt>. The returned sorted set
  330. * is backed by this set, so changes in the returned sorted set are
  331. * reflected in this set, and vice-versa. The returned sorted set
  332. * supports all optional set operations.<p>
  333. *
  334. * The sorted set returned by this method will throw an
  335. * <tt>IllegalArgumentException</tt> if the user attempts to insert an
  336. * element less than <tt>fromElement</tt>.
  337. *
  338. * Note: this method always returns a view that contains its (low)
  339. * endpoint. If you need a view that does not contain this endpoint, and
  340. * the element type allows for calculation of the successor of a specified
  341. * value, merely request a tailSet bounded by
  342. * <tt>successor(lowEndpoint)</tt>. For example, suppose that <tt>s</tt>
  343. * is a sorted set of strings. The following idiom obtains a view
  344. * containing all of the strings in <tt>s</tt> that are strictly greater
  345. * than <tt>low</tt>: <pre>
  346. * SortedSet tail = s.tailSet(low+"\0");
  347. * </pre>
  348. *
  349. * @param fromElement low endpoint (inclusive) of the tailSet.
  350. * @return a view of the portion of this set whose elements are
  351. * greater than or equal to <tt>fromElement</tt>.
  352. * @throws ClassCastException if <tt>fromElement</tt> is not compatible
  353. * with this set's comparator (or, if the set has no comparator,
  354. * if <tt>fromElement</tt> does not implement <tt>Comparable</tt>).
  355. * @throws IllegalArgumentException if this set is itself a subSet,
  356. * headSet, or tailSet, and <tt>fromElement</tt> is not within the
  357. * specified range of the subSet, headSet, or tailSet.
  358. * @throws NullPointerException if <tt>fromElement</tt> is <tt>null</tt>
  359. * and this set uses natural ordering, or its comparator does
  360. * not tolerate <tt>null</tt> elements.
  361. */
  362. public SortedSet tailSet(Object fromElement) {
  363. return new TreeSet(m.tailMap(fromElement));
  364. }
  365. /**
  366. * Returns the comparator used to order this sorted set, or <tt>null</tt>
  367. * if this tree set uses its elements natural ordering.
  368. *
  369. * @return the comparator used to order this sorted set, or <tt>null</tt>
  370. * if this tree set uses its elements natural ordering.
  371. */
  372. public Comparator comparator() {
  373. return m.comparator();
  374. }
  375. /**
  376. * Returns the first (lowest) element currently in this sorted set.
  377. *
  378. * @return the first (lowest) element currently in this sorted set.
  379. * @throws NoSuchElementException sorted set is empty.
  380. */
  381. public Object first() {
  382. return m.firstKey();
  383. }
  384. /**
  385. * Returns the last (highest) element currently in this sorted set.
  386. *
  387. * @return the last (highest) element currently in this sorted set.
  388. * @throws NoSuchElementException sorted set is empty.
  389. */
  390. public Object last() {
  391. return m.lastKey();
  392. }
  393. /**
  394. * Returns a shallow copy of this <tt>TreeSet</tt> instance. (The elements
  395. * themselves are not cloned.)
  396. *
  397. * @return a shallow copy of this set.
  398. */
  399. public Object clone() {
  400. TreeSet clone = null;
  401. try {
  402. clone = (TreeSet)super.clone();
  403. } catch (CloneNotSupportedException e) {
  404. throw new InternalError();
  405. }
  406. clone.m = new TreeMap(m);
  407. clone.keySet = clone.m.keySet();
  408. return clone;
  409. }
  410. /**
  411. * Save the state of the <tt>TreeSet</tt> instance to a stream (that is,
  412. * serialize it).
  413. *
  414. * @serialData Emits the comparator used to order this set, or
  415. * <tt>null</tt> if it obeys its elements' natural ordering
  416. * (Object), followed by the size of the set (the number of
  417. * elements it contains) (int), followed by all of its
  418. * elements (each an Object) in order (as determined by the
  419. * set's Comparator, or by the elements' natural ordering if
  420. * the set has no Comparator).
  421. */
  422. private void writeObject(java.io.ObjectOutputStream s)
  423. throws java.io.IOException {
  424. // Write out any hidden stuff
  425. s.defaultWriteObject();
  426. // Write out Comparator
  427. s.writeObject(m.comparator());
  428. // Write out size
  429. s.writeInt(m.size());
  430. // Write out all elements in the proper order.
  431. for (Iterator i=m.keySet().iterator(); i.hasNext(); )
  432. s.writeObject(i.next());
  433. }
  434. /**
  435. * Reconstitute the <tt>TreeSet</tt> instance from a stream (that is,
  436. * deserialize it).
  437. */
  438. private void readObject(java.io.ObjectInputStream s)
  439. throws java.io.IOException, ClassNotFoundException {
  440. // Read in any hidden stuff
  441. s.defaultReadObject();
  442. // Read in Comparator
  443. Comparator c = (Comparator)s.readObject();
  444. // Create backing TreeMap and keySet view
  445. m = (c==null ? new TreeMap() : new TreeMap(c));
  446. keySet = m.keySet();
  447. // Read in size
  448. int size = s.readInt();
  449. ((TreeMap)m).readTreeSet(size, s, PRESENT);
  450. }
  451. private static final long serialVersionUID = -2479143000061671589L;
  452. }