38 |
* interface. Elements in the Map will be sorted by either a user-provided |
* interface. Elements in the Map will be sorted by either a user-provided |
39 |
* Comparator object, or by the natural ordering of the keys. |
* Comparator object, or by the natural ordering of the keys. |
40 |
* |
* |
41 |
* The algorithms are adopted from Corman, Leiserson, |
* The algorithms are adopted from Corman, Leiserson, and Rivest's |
42 |
* and Rivest's <i>Introduction to Algorithms.</i> In other words, |
* <i>Introduction to Algorithms.</i> TreeMap guarantees O(log n) |
43 |
* I cribbed from the same pseudocode as Sun. <em>Any similarity |
* insertion and deletion of elements. That being said, there is a large |
44 |
* between my code and Sun's (if there is any -- I have never looked |
* enough constant coefficient in front of that "log n" (overhead involved |
45 |
* at Sun's) is a result of this fact.</em> |
* in keeping the tree balanced), that TreeMap may not be the best choice |
46 |
* |
* for small collections. If something is already sorted, you may want to |
47 |
* TreeMap guarantees O(log n) insertion and deletion of elements. That |
* just use a LinkedHashMap to maintain the order while providing O(1) access. |
|
* being said, there is a large enough constant coefficient in front of |
|
|
* that "log n" (overhead involved in keeping the tree |
|
|
* balanced), that TreeMap may not be the best choice for small |
|
|
* collections. |
|
48 |
* |
* |
49 |
* TreeMap is a part of the JDK1.2 Collections API. Null keys are allowed |
* TreeMap is a part of the JDK1.2 Collections API. Null keys are allowed |
50 |
* only if a Comparator is used which can deal with them. Null values are |
* only if a Comparator is used which can deal with them; natural ordering |
51 |
* always allowed. |
* cannot cope with null. Null values are always allowed. Note that the |
52 |
|
* ordering must be <i>consistent with equals</i> to correctly implement |
53 |
|
* the Map interface. If this condition is violated, the map is still |
54 |
|
* well-behaved, but you may have suprising results when comparing it to |
55 |
|
* other maps.<p> |
56 |
|
* |
57 |
|
* This implementation is not synchronized. If you need to share this between |
58 |
|
* multiple threads, do something like:<br> |
59 |
|
* <code>SortedMap m |
60 |
|
* = Collections.synchronizedSortedMap(new TreeMap(...));</code><p> |
61 |
|
* |
62 |
|
* The iterators are <i>fail-fast</i>, meaning that any structural |
63 |
|
* modification, except for <code>remove()</code> called on the iterator |
64 |
|
* itself, cause the iterator to throw a |
65 |
|
* <code>ConcurrentModificationException</code> rather than exhibit |
66 |
|
* non-deterministic behavior. |
67 |
* |
* |
68 |
* @author Jon Zeppieri |
* @author Jon Zeppieri |
69 |
* @author Bryce McKinlay |
* @author Bryce McKinlay |
70 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
71 |
|
* @see Map |
72 |
|
* @see HashMap |
73 |
|
* @see Hashtable |
74 |
|
* @see LinkedHashMap |
75 |
|
* @see Comparable |
76 |
|
* @see Comparator |
77 |
|
* @see Collection |
78 |
|
* @see Collections#synchronizedSortedMap(SortedMap) |
79 |
|
* @since 1.2 |
80 |
|
* @status updated to 1.4 |
81 |
*/ |
*/ |
82 |
public class TreeMap extends AbstractMap |
public class TreeMap extends AbstractMap |
83 |
implements SortedMap, Cloneable, Serializable |
implements SortedMap, Cloneable, Serializable |
84 |
{ |
{ |
85 |
private static final int RED = -1, |
// Implementation note: |
86 |
BLACK = 1; |
// A red-black tree is a binary search tree with the additional properties |
87 |
|
// that all paths to a leaf node visit the same number of black nodes, |
88 |
|
// and no red node has red children. To avoid some null-pointer checks, |
89 |
|
// we use the special node nil which is always black, has no relatives, |
90 |
|
// and has key and value of null (but is not equal to a mapping of null). |
91 |
|
|
92 |
/** Sentinal node, used to avoid null checks for corner cases and make the |
/** |
93 |
delete rebalance code simpler. Note that this must not be static, due |
* Compatible with JDK 1.2. |
94 |
to thread-safety concerns. */ |
*/ |
95 |
transient Node nil = new Node(null, null); |
private static final long serialVersionUID = 919286545866124006L; |
96 |
|
|
97 |
/** The root node of this TreeMap */ |
/** |
98 |
transient Node root = nil; |
* Color status of a node. Package visible for use by nested classes. |
99 |
|
*/ |
100 |
|
static final int RED = -1, |
101 |
|
BLACK = 1; |
102 |
|
|
103 |
/** The size of this TreeMap */ |
/** |
104 |
transient int size = 0; |
* Sentinal node, used to avoid null checks for corner cases and make the |
105 |
|
* delete rebalance code simpler. The rebalance code must never assign |
106 |
|
* the parent, left, or right of nil, but may safely reassign the color |
107 |
|
* to be black. This object must never be used as a key in a TreeMap, or |
108 |
|
* it will break bounds checking of a SubMap. |
109 |
|
*/ |
110 |
|
static final Node nil = new Node(null, null, BLACK); |
111 |
|
static |
112 |
|
{ |
113 |
|
// Nil is self-referential, so we must initialize it after creation. |
114 |
|
nil.parent = nil; |
115 |
|
nil.left = nil; |
116 |
|
nil.right = nil; |
117 |
|
} |
118 |
|
|
119 |
/** Number of modifications */ |
/** |
120 |
transient int modCount = 0; |
* The root node of this TreeMap. |
121 |
|
*/ |
122 |
|
private transient Node root = nil; |
123 |
|
|
124 |
/** This TreeMap's comparator, if any. */ |
/** |
125 |
Comparator comparator = null; |
* The size of this TreeMap. Package visible for use by nested classes. |
126 |
|
*/ |
127 |
|
transient int size; |
128 |
|
|
129 |
static final long serialVersionUID = 919286545866124006L; |
/** |
130 |
|
* The cache for {@link #entrySet()}. |
131 |
|
*/ |
132 |
|
private transient Set entries; |
133 |
|
|
134 |
private static class Node extends BasicMapEntry implements Map.Entry |
/** |
135 |
|
* Counts the number of modifications this TreeMap has undergone, used |
136 |
|
* by Iterators to know when to throw ConcurrentModificationExceptions. |
137 |
|
* Package visible for use by nested classes. |
138 |
|
*/ |
139 |
|
transient int modCount; |
140 |
|
|
141 |
|
/** |
142 |
|
* This TreeMap's comparator, or null for natural ordering. |
143 |
|
* Package visible for use by nested classes. |
144 |
|
* @serial the comparator ordering this tree, or null |
145 |
|
*/ |
146 |
|
final Comparator comparator; |
147 |
|
|
148 |
|
/** |
149 |
|
* Class to represent an entry in the tree. Holds a single key-value pair, |
150 |
|
* plus pointers to parent and child nodes. |
151 |
|
* |
152 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
153 |
|
*/ |
154 |
|
private static final class Node extends BasicMapEntry |
155 |
{ |
{ |
156 |
|
// All fields package visible for use by nested classes. |
157 |
|
/** The color of this node. */ |
158 |
int color; |
int color; |
|
Node left; |
|
|
Node right; |
|
|
Node parent; |
|
159 |
|
|
160 |
Node(Object key, Object value) |
/** The left child node. */ |
161 |
|
Node left = nil; |
162 |
|
/** The right child node. */ |
163 |
|
Node right = nil; |
164 |
|
/** The parent node. */ |
165 |
|
Node parent = nil; |
166 |
|
|
167 |
|
/** |
168 |
|
* Simple constructor. |
169 |
|
* @param key the key |
170 |
|
* @param value the value |
171 |
|
*/ |
172 |
|
Node(Object key, Object value, int color) |
173 |
{ |
{ |
174 |
super(key, value); |
super(key, value); |
175 |
this.color = BLACK; |
this.color = color; |
176 |
} |
} |
177 |
} |
} |
178 |
|
|
179 |
/** |
/** |
180 |
* Instantiate a new TreeMap with no elements, using the keys' |
* Instantiate a new TreeMap with no elements, using the keys' natural |
181 |
* natural ordering to sort. |
* ordering to sort. All entries in the map must have a key which implements |
182 |
|
* Comparable, and which are <i>mutually comparable</i>, otherwise map |
183 |
|
* operations may throw a {@link ClassCastException}. Attempts to use |
184 |
|
* a null key will throw a {@link NullPointerException}. |
185 |
* |
* |
186 |
* @see java.lang.Comparable |
* @see Comparable |
187 |
*/ |
*/ |
188 |
public TreeMap() |
public TreeMap() |
189 |
{ |
{ |
190 |
|
this((Comparator) null); |
191 |
} |
} |
192 |
|
|
193 |
/** |
/** |
194 |
* Instantiate a new TreeMap with no elements, using the provided |
* Instantiate a new TreeMap with no elements, using the provided comparator |
195 |
* comparator to sort. |
* to sort. All entries in the map must have keys which are mutually |
196 |
|
* comparable by the Comparator, otherwise map operations may throw a |
197 |
|
* {@link ClassCastException}. |
198 |
* |
* |
199 |
* @param oComparator a Comparator object, used to sort |
* @param comparator the sort order for the keys of this map, or null |
200 |
* the keys of this SortedMap |
* for the natural order |
201 |
*/ |
*/ |
202 |
public TreeMap(Comparator c) |
public TreeMap(Comparator c) |
203 |
{ |
{ |
205 |
} |
} |
206 |
|
|
207 |
/** |
/** |
208 |
* Instantiate a new TreeMap, initializing it with all of the |
* Instantiate a new TreeMap, initializing it with all of the elements in |
209 |
* elements in the provided Map. The elements will be sorted |
* the provided Map. The elements will be sorted using the natural |
210 |
* using the natural ordering of the keys. |
* ordering of the keys. This algorithm runs in n*log(n) time. All entries |
211 |
* |
* in the map must have keys which implement Comparable and are mutually |
212 |
* @param map a Map, whose keys will be put into |
* comparable, otherwise map operations may throw a |
213 |
* this TreeMap |
* {@link ClassCastException}. |
|
* |
|
|
* @throws ClassCastException if the keys in the provided |
|
|
* Map do not implement |
|
|
* Comparable |
|
214 |
* |
* |
215 |
* @see java.lang.Comparable |
* @param map a Map, whose entries will be put into this TreeMap |
216 |
|
* @throws ClassCastException if the keys in the provided Map are not |
217 |
|
* comparable |
218 |
|
* @throws NullPointerException if map is null |
219 |
|
* @see Comparable |
220 |
*/ |
*/ |
221 |
public TreeMap(Map map) |
public TreeMap(Map map) |
222 |
{ |
{ |
223 |
|
this((Comparator) null); |
224 |
putAll(map); |
putAll(map); |
225 |
} |
} |
226 |
|
|
227 |
/** |
/** |
228 |
* Instantiate a new TreeMap, initializing it with all of the |
* Instantiate a new TreeMap, initializing it with all of the elements in |
229 |
* elements in the provided SortedMap. The elements will be sorted |
* the provided SortedMap. The elements will be sorted using the same |
230 |
* using the same method as in the provided SortedMap. |
* comparator as in the provided SortedMap. This runs in linear time. |
231 |
|
* |
232 |
|
* @param sm a SortedMap, whose entries will be put into this TreeMap |
233 |
|
* @throws NullPointerException if sm is null |
234 |
*/ |
*/ |
235 |
public TreeMap(SortedMap sm) |
public TreeMap(SortedMap sm) |
236 |
{ |
{ |
237 |
this(sm.comparator()); |
this(sm.comparator()); |
238 |
|
int pos = sm.size(); |
|
int sm_size = sm.size(); |
|
239 |
Iterator itr = sm.entrySet().iterator(); |
Iterator itr = sm.entrySet().iterator(); |
240 |
|
|
241 |
fabricateTree(sm_size); |
fabricateTree(pos); |
242 |
Node node = firstNode(); |
Node node = firstNode(); |
243 |
|
|
244 |
for (int i = 0; i < sm_size; i++) |
while (--pos >= 0) |
245 |
{ |
{ |
246 |
Map.Entry me = (Map.Entry) itr.next(); |
Map.Entry me = (Map.Entry) itr.next(); |
247 |
node.key = me.getKey(); |
node.key = me.getKey(); |
248 |
node.value = me.getValue(); |
node.value = me.getValue(); |
249 |
node = successor(node); |
node = successor(node); |
250 |
} |
} |
251 |
} |
} |
252 |
|
|
253 |
public int size() |
/** |
254 |
{ |
* Clears the Map so it has no keys. This is O(1). |
255 |
return size; |
*/ |
|
} |
|
|
|
|
256 |
public void clear() |
public void clear() |
257 |
{ |
{ |
258 |
modCount++; |
if (size > 0) |
259 |
root = nil; |
{ |
260 |
// nil node could have a residual parent reference, clear it for GC. |
modCount++; |
261 |
nil.parent = null; |
root = nil; |
262 |
size = 0; |
size = 0; |
263 |
|
} |
264 |
} |
} |
265 |
|
|
266 |
|
/** |
267 |
|
* Returns a shallow clone of this TreeMap. The Map itself is cloned, |
268 |
|
* but its contents are not. |
269 |
|
* |
270 |
|
* @return the clone |
271 |
|
*/ |
272 |
public Object clone() |
public Object clone() |
273 |
{ |
{ |
274 |
TreeMap copy = null; |
TreeMap copy = null; |
279 |
catch (CloneNotSupportedException x) |
catch (CloneNotSupportedException x) |
280 |
{ |
{ |
281 |
} |
} |
282 |
// Each instance must have a unique sentinal. |
copy.entries = null; |
|
copy.nil = new Node(null, null); |
|
283 |
copy.fabricateTree(size); |
copy.fabricateTree(size); |
284 |
|
|
285 |
Node node = firstNode(); |
Node node = firstNode(); |
286 |
Node cnode = copy.firstNode(); |
Node cnode = copy.firstNode(); |
287 |
|
|
288 |
while (node != nil) |
while (node != nil) |
289 |
{ |
{ |
290 |
cnode.key = node.key; |
cnode.key = node.key; |
291 |
cnode.value = node.value; |
cnode.value = node.value; |
292 |
node = successor(node); |
node = successor(node); |
293 |
cnode = copy.successor(cnode); |
cnode = copy.successor(cnode); |
294 |
} |
} |
295 |
return copy; |
return copy; |
296 |
} |
} |
297 |
|
|
298 |
|
/** |
299 |
|
* Return the comparator used to sort this map, or null if it is by |
300 |
|
* natural order. |
301 |
|
* |
302 |
|
* @return the map's comparator |
303 |
|
*/ |
304 |
public Comparator comparator() |
public Comparator comparator() |
305 |
{ |
{ |
306 |
return comparator; |
return comparator; |
307 |
} |
} |
308 |
|
|
309 |
|
/** |
310 |
|
* Returns true if the map contains a mapping for the given key. |
311 |
|
* |
312 |
|
* @param key the key to look for |
313 |
|
* @return true if the key has a mapping |
314 |
|
* @throws ClassCastException if key is not comparable to map elements |
315 |
|
* @throws NullPointerException if key is null and the comparator is not |
316 |
|
* tolerant of nulls |
317 |
|
*/ |
318 |
public boolean containsKey(Object key) |
public boolean containsKey(Object key) |
319 |
{ |
{ |
320 |
return getNode(key) != nil; |
return getNode(key) != nil; |
321 |
} |
} |
322 |
|
|
323 |
|
/** |
324 |
|
* Returns true if the map contains at least one mapping to the given value. |
325 |
|
* This requires linear time. |
326 |
|
* |
327 |
|
* @param value the value to look for |
328 |
|
* @return true if the value appears in a mapping |
329 |
|
*/ |
330 |
public boolean containsValue(Object value) |
public boolean containsValue(Object value) |
331 |
{ |
{ |
332 |
Node node = firstNode(); |
Node node = firstNode(); |
|
Object currentVal; |
|
|
|
|
333 |
while (node != nil) |
while (node != nil) |
334 |
{ |
{ |
335 |
currentVal = node.getValue(); |
if (equals(value, node.value)) |
336 |
|
return true; |
337 |
if (value == null ? currentVal == null : value.equals (currentVal)) |
node = successor(node); |
|
return true; |
|
|
|
|
|
node = successor(node); |
|
338 |
} |
} |
339 |
return false; |
return false; |
340 |
} |
} |
341 |
|
|
342 |
|
/** |
343 |
|
* Returns a "set view" of this TreeMap's entries. The set is backed by |
344 |
|
* the TreeMap, so changes in one show up in the other. The set supports |
345 |
|
* element removal, but not element addition.<p> |
346 |
|
* |
347 |
|
* Note that the iterators for all three views, from keySet(), entrySet(), |
348 |
|
* and values(), traverse the TreeMap in sorted sequence. |
349 |
|
* |
350 |
|
* @return a set view of the entries |
351 |
|
* @see #keySet() |
352 |
|
* @see #values() |
353 |
|
* @see Map.Entry |
354 |
|
*/ |
355 |
public Set entrySet() |
public Set entrySet() |
356 |
{ |
{ |
357 |
// Create an AbstractSet with custom implementations of those methods that |
if (entries == null) |
358 |
// can be overriden easily and efficiently. |
// Create an AbstractSet with custom implementations of those methods |
359 |
return new AbstractSet() |
// that can be overriden easily and efficiently. |
360 |
{ |
entries = new AbstractSet() |
|
public int size() |
|
|
{ |
|
|
return size; |
|
|
} |
|
|
|
|
|
public Iterator iterator() |
|
|
{ |
|
|
return new TreeIterator(TreeIterator.ENTRIES); |
|
|
} |
|
|
|
|
|
public void clear() |
|
361 |
{ |
{ |
362 |
TreeMap.this.clear(); |
public int size() |
363 |
} |
{ |
364 |
|
return size; |
365 |
|
} |
366 |
|
|
367 |
public boolean contains(Object o) |
public Iterator iterator() |
368 |
{ |
{ |
369 |
if (!(o instanceof Map.Entry)) |
return new TreeIterator(ENTRIES); |
370 |
return false; |
} |
371 |
Map.Entry me = (Map.Entry) o; |
|
372 |
Node n = getNode(me.getKey()); |
public void clear() |
373 |
return (n != nil && me.getValue().equals(n.value)); |
{ |
374 |
} |
TreeMap.this.clear(); |
375 |
|
} |
376 |
public boolean remove(Object o) |
|
377 |
{ |
public boolean contains(Object o) |
378 |
if (!(o instanceof Map.Entry)) |
{ |
379 |
return false; |
if (! (o instanceof Map.Entry)) |
380 |
Map.Entry me = (Map.Entry) o; |
return false; |
381 |
Node n = getNode(me.getKey()); |
Map.Entry me = (Map.Entry) o; |
382 |
if (n != nil && me.getValue().equals(n.value)) |
Node n = getNode(me.getKey()); |
383 |
{ |
return n != nil && AbstractSet.equals(me.getValue(), n.value); |
|
removeNode(n); |
|
|
return true; |
|
|
} |
|
|
return false; |
|
384 |
} |
} |
385 |
}; |
|
386 |
|
public boolean remove(Object o) |
387 |
|
{ |
388 |
|
if (! (o instanceof Map.Entry)) |
389 |
|
return false; |
390 |
|
Map.Entry me = (Map.Entry) o; |
391 |
|
Node n = getNode(me.getKey()); |
392 |
|
if (n != nil && AbstractSet.equals(me.getValue(), n.value)) |
393 |
|
{ |
394 |
|
removeNode(n); |
395 |
|
return true; |
396 |
|
} |
397 |
|
return false; |
398 |
|
} |
399 |
|
}; |
400 |
|
return entries; |
401 |
} |
} |
402 |
|
|
403 |
|
/** |
404 |
|
* Returns the first (lowest) key in the map. |
405 |
|
* |
406 |
|
* @return the first key |
407 |
|
* @throws NoSuchElementException if the map is empty |
408 |
|
*/ |
409 |
public Object firstKey() |
public Object firstKey() |
410 |
{ |
{ |
411 |
if (root == nil) |
if (root == nil) |
412 |
throw new NoSuchElementException("empty"); |
throw new NoSuchElementException(); |
413 |
return firstNode().getKey(); |
return firstNode().key; |
|
} |
|
|
|
|
|
private Node firstNode() |
|
|
{ |
|
|
if (root == nil) |
|
|
return nil; |
|
|
Node node = root; |
|
|
while (node.left != nil) |
|
|
node = node.left; |
|
|
return node; |
|
414 |
} |
} |
415 |
|
|
416 |
public Object lastKey() |
/** |
417 |
{ |
* Return the value in this TreeMap associated with the supplied key, |
418 |
if (root == nil) |
* or <code>null</code> if the key maps to nothing. NOTE: Since the value |
419 |
throw new NoSuchElementException("empty"); |
* could also be null, you must use containsKey to see if this key |
420 |
return lastNode().getKey(); |
* actually maps to something. |
421 |
} |
* |
422 |
|
* @param key the key for which to fetch an associated value |
423 |
private Node lastNode() |
* @return what the key maps to, if present |
424 |
{ |
* @throws ClassCastException if key is not comparable to elements in the map |
425 |
if (root == nil) |
* @throws NullPointerException if key is null but the comparator does not |
426 |
return nil; |
* tolerate nulls |
427 |
Node node = root; |
* @see #put(Object, Object) |
428 |
while (node.right != nil) |
* @see #containsKey(Object) |
429 |
node = node.right; |
*/ |
|
return node; |
|
|
} |
|
|
|
|
430 |
public Object get(Object key) |
public Object get(Object key) |
431 |
{ |
{ |
432 |
|
// Exploit fact that nil.value == null. |
433 |
return getNode(key).value; |
return getNode(key).value; |
434 |
} |
} |
|
|
|
|
/** Return the TreeMap.Node associated with KEY, or the nil node if no such |
|
|
node exists in the tree. */ |
|
|
private Node getNode(Object key) |
|
|
{ |
|
|
int comparison; |
|
|
Node current = root; |
|
435 |
|
|
436 |
while (current != nil) |
/** |
437 |
{ |
* Returns a view of this Map including all entries with keys less than |
438 |
comparison = compare(key, current.key); |
* <code>toKey</code>. The returned map is backed by the original, so changes |
439 |
if (comparison > 0) |
* in one appear in the other. The submap will throw an |
440 |
current = current.right; |
* {@link IllegalArgumentException} for any attempt to access or add an |
441 |
else if (comparison < 0) |
* element beyond the specified cutoff. The returned map does not include |
442 |
current = current.left; |
* the endpoint; if you want inclusion, pass the successor element. |
443 |
else |
* |
444 |
return current; |
* @param toKey the (exclusive) cutoff point |
445 |
} |
* @return a view of the map less than the cutoff |
446 |
return current; |
* @throws ClassCastException if <code>toKey</code> is not compatible with |
447 |
|
* the comparator (or is not Comparable, for natural ordering) |
448 |
|
* @throws NullPointerException if toKey is null, but the comparator does not |
449 |
|
* tolerate null elements |
450 |
|
*/ |
451 |
|
public SortedMap headMap(Object toKey) |
452 |
|
{ |
453 |
|
return new SubMap(nil, toKey); |
454 |
} |
} |
455 |
|
|
456 |
|
/** |
457 |
|
* Returns a "set view" of this TreeMap's keys. The set is backed by the |
458 |
|
* TreeMap, so changes in one show up in the other. The set supports |
459 |
|
* element removal, but not element addition. |
460 |
|
* |
461 |
|
* @return a set view of the keys |
462 |
|
* @see #values() |
463 |
|
* @see #entrySet() |
464 |
|
*/ |
465 |
public Set keySet() |
public Set keySet() |
466 |
{ |
{ |
467 |
// Create an AbstractSet with custom implementations of those methods that |
if (keys == null) |
468 |
// can be overriden easily and efficiently. |
// Create an AbstractSet with custom implementations of those methods |
469 |
return new AbstractSet() |
// that can be overriden easily and efficiently. |
470 |
{ |
keys = new AbstractSet() |
|
public int size() |
|
471 |
{ |
{ |
472 |
return size; |
public int size() |
473 |
} |
{ |
474 |
|
return size; |
475 |
public Iterator iterator() |
} |
|
{ |
|
|
return new TreeIterator(TreeIterator.KEYS); |
|
|
} |
|
476 |
|
|
477 |
public void clear() |
public Iterator iterator() |
478 |
{ |
{ |
479 |
TreeMap.this.clear(); |
return new TreeIterator(KEYS); |
480 |
} |
} |
481 |
|
|
482 |
public boolean contains(Object o) |
public void clear() |
483 |
{ |
{ |
484 |
return TreeMap.this.containsKey(o); |
TreeMap.this.clear(); |
485 |
} |
} |
486 |
|
|
487 |
public boolean remove(Object key) |
public boolean contains(Object o) |
488 |
{ |
{ |
489 |
Node n = getNode(key); |
return containsKey(o); |
490 |
if (n == nil) |
} |
491 |
return false; |
|
492 |
TreeMap.this.removeNode(n); |
public boolean remove(Object key) |
493 |
return true; |
{ |
494 |
} |
Node n = getNode(key); |
495 |
}; |
if (n == nil) |
496 |
|
return false; |
497 |
|
removeNode(n); |
498 |
|
return true; |
499 |
|
} |
500 |
|
}; |
501 |
|
return keys; |
502 |
|
} |
503 |
|
|
504 |
|
/** |
505 |
|
* Returns the last (highest) key in the map. |
506 |
|
* |
507 |
|
* @return the last key |
508 |
|
* @throws NoSuchElementException if the map is empty |
509 |
|
*/ |
510 |
|
public Object lastKey() |
511 |
|
{ |
512 |
|
if (root == nil) |
513 |
|
throw new NoSuchElementException("empty"); |
514 |
|
return lastNode().key; |
515 |
} |
} |
516 |
|
|
517 |
|
/** |
518 |
|
* Puts the supplied value into the Map, mapped by the supplied key. |
519 |
|
* The value may be retrieved by any object which <code>equals()</code> |
520 |
|
* this key. NOTE: Since the prior value could also be null, you must |
521 |
|
* first use containsKey if you want to see if you are replacing the |
522 |
|
* key's mapping. |
523 |
|
* |
524 |
|
* @param key the key used to locate the value |
525 |
|
* @param value the value to be stored in the HashMap |
526 |
|
* @return the prior mapping of the key, or null if there was none |
527 |
|
* @throws ClassCastException if key is not comparable to current map keys |
528 |
|
* @throws NullPointerException if key is null, but the comparator does |
529 |
|
* not tolerate nulls |
530 |
|
* @see #get(Object) |
531 |
|
* @see Object#equals(Object) |
532 |
|
*/ |
533 |
public Object put(Object key, Object value) |
public Object put(Object key, Object value) |
534 |
{ |
{ |
|
modCount++; |
|
535 |
Node current = root; |
Node current = root; |
536 |
Node parent = nil; |
Node parent = nil; |
537 |
int comparison = 0; |
int comparison = 0; |
538 |
|
|
539 |
// Find new node's parent. |
// Find new node's parent. |
540 |
while (current != nil) |
while (current != nil) |
541 |
{ |
{ |
542 |
parent = current; |
parent = current; |
543 |
comparison = compare(key, current.key); |
comparison = compare(key, current.key); |
544 |
if (comparison > 0) |
if (comparison > 0) |
545 |
current = current.right; |
current = current.right; |
546 |
else if (comparison < 0) |
else if (comparison < 0) |
547 |
current = current.left; |
current = current.left; |
548 |
else |
else // Key already in tree. |
549 |
{ |
return current.setValue(value); |
|
// Key already in tree. |
|
|
Object r = current.value; |
|
|
current.value = value; |
|
|
return r; |
|
|
} |
|
550 |
} |
} |
551 |
|
|
552 |
// Set up new node. |
// Set up new node. |
553 |
Node n = new Node(key, value); |
Node n = new Node(key, value, RED); |
|
n.color = RED; |
|
554 |
n.parent = parent; |
n.parent = parent; |
555 |
n.left = nil; |
|
|
n.right = nil; |
|
|
|
|
556 |
// Insert node in tree. |
// Insert node in tree. |
557 |
|
modCount++; |
558 |
size++; |
size++; |
559 |
if (parent == nil) |
if (parent == nil) |
560 |
{ |
{ |
561 |
// Special case: inserting into an empty tree. |
// Special case inserting into an empty tree. |
562 |
root = n; |
root = n; |
563 |
n.color = BLACK; |
return null; |
|
return null; |
|
564 |
} |
} |
565 |
else if (comparison > 0) |
if (comparison > 0) |
566 |
parent.right = n; |
parent.right = n; |
567 |
else |
else |
568 |
parent.left = n; |
parent.left = n; |
569 |
|
|
570 |
// Rebalance after insert. |
// Rebalance after insert. |
571 |
insertFixup(n); |
insertFixup(n); |
|
//verifyTree(); |
|
572 |
return null; |
return null; |
573 |
} |
} |
574 |
|
|
575 |
/** Maintain red-black balance after inserting a new node. */ |
/** |
576 |
private void insertFixup(Node n) |
* Copies all elements of the given map into this hashtable. If this table |
577 |
{ |
* already has a mapping for a key, the new mapping replaces the current |
578 |
// Only need to rebalance when parent is a RED node, and while at least |
* one. |
579 |
// 2 levels deep into the tree (ie: node has a grandparent). |
* |
580 |
while (n != root && n.parent.parent != nil && n.parent.color == RED) |
* @param m the map to be hashed into this |
581 |
{ |
* @throws ClassCastException if a key in m is not comparable with keys |
582 |
if (n.parent == n.parent.parent.left) |
* in the map |
583 |
{ |
* @throws NullPointerException if a key in m is null, and the comparator |
584 |
Node uncle = n.parent.parent.right; |
* does not tolerate nulls |
585 |
if (uncle != nil && uncle.color == RED) |
*/ |
|
{ |
|
|
n.parent.color = BLACK; |
|
|
uncle.color = BLACK; |
|
|
n.parent.parent.color = RED; |
|
|
n = n.parent.parent; |
|
|
} |
|
|
else // Uncle is BLACK. |
|
|
{ |
|
|
if (n == n.parent.right) |
|
|
{ |
|
|
// Make n a left child. |
|
|
n = n.parent; |
|
|
rotateLeft(n); |
|
|
} |
|
|
|
|
|
// Recolor and rotate. |
|
|
n.parent.color = BLACK; |
|
|
n.parent.parent.color = RED; |
|
|
rotateRight(n.parent.parent); |
|
|
} |
|
|
} |
|
|
else |
|
|
{ |
|
|
// Mirror image of above code. |
|
|
Node uncle = n.parent.parent.left; |
|
|
if (uncle != nil && uncle.color == RED) |
|
|
{ |
|
|
n.parent.color = BLACK; |
|
|
uncle.color = BLACK; |
|
|
n.parent.parent.color = RED; |
|
|
n = n.parent.parent; |
|
|
} |
|
|
else |
|
|
{ |
|
|
if (n == n.parent.left) |
|
|
{ |
|
|
n = n.parent; |
|
|
rotateRight(n); |
|
|
} |
|
|
n.parent.color = BLACK; |
|
|
n.parent.parent.color = RED; |
|
|
rotateLeft(n.parent.parent); |
|
|
} |
|
|
} |
|
|
} |
|
|
root.color = BLACK; |
|
|
} |
|
|
|
|
586 |
public void putAll(Map m) |
public void putAll(Map m) |
587 |
{ |
{ |
588 |
Iterator itr = m.entrySet().iterator(); |
Iterator itr = m.entrySet().iterator(); |
589 |
int msize = m.size(); |
int pos = m.size(); |
590 |
Map.Entry e; |
while (--pos >= 0) |
|
|
|
|
for (int i = 0; i < msize; i++) |
|
591 |
{ |
{ |
592 |
e = (Map.Entry) itr.next(); |
Map.Entry e = (Map.Entry) itr.next(); |
593 |
put(e.getKey(), e.getValue()); |
put(e.getKey(), e.getValue()); |
594 |
} |
} |
595 |
} |
} |
596 |
|
|
597 |
|
/** |
598 |
|
* Removes from the TreeMap and returns the value which is mapped by the |
599 |
|
* supplied key. If the key maps to nothing, then the TreeMap remains |
600 |
|
* unchanged, and <code>null</code> is returned. NOTE: Since the value |
601 |
|
* could also be null, you must use containsKey to see if you are |
602 |
|
* actually removing a mapping. |
603 |
|
* |
604 |
|
* @param key the key used to locate the value to remove |
605 |
|
* @return whatever the key mapped to, if present |
606 |
|
* @throws ClassCastException if key is not comparable to current map keys |
607 |
|
* @throws NullPointerException if key is null, but the comparator does |
608 |
|
* not tolerate nulls |
609 |
|
*/ |
610 |
public Object remove(Object key) |
public Object remove(Object key) |
611 |
{ |
{ |
612 |
Node n = getNode(key); |
Node n = getNode(key); |
613 |
if (n != nil) |
if (n == nil) |
614 |
{ |
return null; |
615 |
removeNode(n); |
removeNode(n); |
616 |
return n.value; |
return n.value; |
|
} |
|
|
return null; |
|
617 |
} |
} |
|
|
|
|
// Remove node from tree. This will increment modCount and decrement size. |
|
|
// Node must exist in the tree. |
|
|
private void removeNode(Node node) // z |
|
|
{ |
|
|
Node splice; // y |
|
|
Node child; // x |
|
|
|
|
|
modCount++; |
|
|
size--; |
|
618 |
|
|
619 |
// Find splice, the node at the position to actually remove from the tree. |
/** |
620 |
if (node.left == nil || node.right == nil) |
* Returns the number of key-value mappings currently in this Map. |
621 |
{ |
* |
622 |
// Node to be deleted has 0 or 1 children. |
* @return the size |
623 |
splice = node; |
*/ |
624 |
if (node.left == nil) |
public int size() |
625 |
child = node.right; |
{ |
626 |
else |
return size; |
627 |
child = node.left; |
} |
|
} |
|
|
else |
|
|
{ |
|
|
// Node has 2 children. Splice is node's successor, and will be |
|
|
// swapped with node since we can't remove node directly. |
|
|
splice = node.right; |
|
|
while (splice.left != nil) |
|
|
splice = splice.left; |
|
|
child = splice.right; |
|
|
} |
|
628 |
|
|
629 |
// Unlink splice from the tree. |
/** |
630 |
Node parent = splice.parent; |
* Returns a view of this Map including all entries with keys greater or |
631 |
child.parent = parent; |
* equal to <code>fromKey</code> and less than <code>toKey</code> (a |
632 |
if (parent != nil) |
* half-open interval). The returned map is backed by the original, so |
633 |
{ |
* changes in one appear in the other. The submap will throw an |
634 |
if (splice == parent.left) |
* {@link IllegalArgumentException} for any attempt to access or add an |
635 |
parent.left = child; |
* element beyond the specified cutoffs. The returned map includes the low |
636 |
else |
* endpoint but not the high; if you want to reverse this behavior on |
637 |
parent.right = child; |
* either end, pass in the successor element. |
638 |
} |
* |
639 |
else |
* @param fromKey the (inclusive) low cutoff point |
640 |
root = child; |
* @param toKey the (exclusive) high cutoff point |
641 |
|
* @return a view of the map between the cutoffs |
642 |
|
* @throws ClassCastException if either cutoff is not compatible with |
643 |
|
* the comparator (or is not Comparable, for natural ordering) |
644 |
|
* @throws NullPointerException if fromKey or toKey is null, but the |
645 |
|
* comparator does not tolerate null elements |
646 |
|
* @throws IllegalArgumentException if fromKey is greater than toKey |
647 |
|
*/ |
648 |
|
public SortedMap subMap(Object fromKey, Object toKey) |
649 |
|
{ |
650 |
|
return new SubMap(fromKey, toKey); |
651 |
|
} |
652 |
|
|
653 |
// Keep track of splice's color in case it gets changed in the swap. |
/** |
654 |
int spliceColor = splice.color; |
* Returns a view of this Map including all entries with keys greater or |
655 |
|
* equal to <code>fromKey</code>. The returned map is backed by the |
656 |
|
* original, so changes in one appear in the other. The submap will throw an |
657 |
|
* {@link IllegalArgumentException} for any attempt to access or add an |
658 |
|
* element beyond the specified cutoff. The returned map includes the |
659 |
|
* endpoint; if you want to exclude it, pass in the successor element. |
660 |
|
* |
661 |
|
* @param fromKey the (inclusive) low cutoff point |
662 |
|
* @return a view of the map above the cutoff |
663 |
|
* @throws ClassCastException if <code>fromKey</code> is not compatible with |
664 |
|
* the comparator (or is not Comparable, for natural ordering) |
665 |
|
* @throws NullPointerException if fromKey is null, but the comparator |
666 |
|
* does not tolerate null elements |
667 |
|
*/ |
668 |
|
public SortedMap tailMap(Object fromKey) |
669 |
|
{ |
670 |
|
return new SubMap(fromKey, nil); |
671 |
|
} |
672 |
|
|
673 |
/* |
/** |
674 |
if (splice != node) |
* Returns a "collection view" (or "bag view") of this TreeMap's values. |
675 |
{ |
* The collection is backed by the TreeMap, so changes in one show up |
676 |
node.key = splice.key; |
* in the other. The collection supports element removal, but not element |
677 |
node.value = splice.value; |
* addition. |
678 |
} |
* |
679 |
*/ |
* @return a bag view of the values |
680 |
if (splice != node) |
* @see #keySet() |
681 |
|
* @see #entrySet() |
682 |
|
*/ |
683 |
|
public Collection values() |
684 |
|
{ |
685 |
|
if (values == null) |
686 |
|
// We don't bother overriding many of the optional methods, as doing so |
687 |
|
// wouldn't provide any significant performance advantage. |
688 |
|
values = new AbstractCollection() |
689 |
{ |
{ |
690 |
// Swap SPLICE for NODE. Some implementations optimize here by simply |
public int size() |
691 |
// swapping the values, but we can't do that: if an iterator was |
{ |
692 |
// referencing a node in its "next" field, and that node got swapped, |
return size; |
693 |
// things would get confused. |
} |
694 |
if (node == root) |
|
695 |
{ |
public Iterator iterator() |
696 |
root = splice; |
{ |
697 |
} |
return new TreeIterator(VALUES); |
698 |
else |
} |
699 |
{ |
|
700 |
if (node.parent.left == node) |
public void clear() |
701 |
node.parent.left = splice; |
{ |
702 |
else |
TreeMap.this.clear(); |
703 |
node.parent.right = splice; |
} |
704 |
} |
}; |
705 |
splice.parent = node.parent; |
return values; |
706 |
splice.left = node.left; |
} |
|
splice.right = node.right; |
|
|
splice.left.parent = splice; |
|
|
splice.right.parent = splice; |
|
|
splice.color = node.color; |
|
|
} |
|
707 |
|
|
708 |
if (spliceColor == BLACK) |
/** |
709 |
deleteFixup (child); |
* Compares two elements by the set comparator, or by natural ordering. |
710 |
|
* Package visible for use by nested classes. |
711 |
//verifyTree(); |
* |
712 |
|
* @param o1 the first object |
713 |
|
* @param o2 the second object |
714 |
|
* @throws ClassCastException if o1 and o2 are not mutually comparable, |
715 |
|
* or are not Comparable with natural ordering |
716 |
|
* @throws NullPointerException if o1 or o2 is null with natural ordering |
717 |
|
*/ |
718 |
|
final int compare(Object o1, Object o2) |
719 |
|
{ |
720 |
|
return (comparator == null |
721 |
|
? ((Comparable) o1).compareTo(o2) |
722 |
|
: comparator.compare(o1, o2)); |
723 |
} |
} |
724 |
|
|
725 |
/** Maintain red-black balance after deleting a node. */ |
/** |
726 |
private void deleteFixup (Node node) |
* Maintain red-black balance after deleting a node. |
727 |
|
* |
728 |
|
* @param node the child of the node just deleted, possibly nil |
729 |
|
* @param parent the parent of the node just deleted, never nil |
730 |
|
*/ |
731 |
|
private void deleteFixup(Node node, Node parent) |
732 |
{ |
{ |
733 |
// A black node has been removed, so we need to rebalance to avoid |
// if (parent == nil) |
734 |
|
// throw new InternalError(); |
735 |
|
// If a black node has been removed, we need to rebalance to avoid |
736 |
// violating the "same number of black nodes on any path" rule. If |
// violating the "same number of black nodes on any path" rule. If |
737 |
// node is red, we can simply recolor it black and all is well. |
// node is red, we can simply recolor it black and all is well. |
738 |
while (node != root && node.color == BLACK) |
while (node != root && node.color == BLACK) |
739 |
{ |
{ |
740 |
if (node == node.parent.left) |
if (node == parent.left) |
741 |
{ |
{ |
742 |
// Rebalance left side. |
// Rebalance left side. |
743 |
Node sibling = node.parent.right; |
Node sibling = parent.right; |
744 |
if (sibling.color == RED) |
// if (sibling == nil) |
745 |
{ |
// throw new InternalError(); |
746 |
|
if (sibling.color == RED) |
747 |
|
{ |
748 |
|
// Case 1: Sibling is red. |
749 |
|
// Recolor sibling and parent, and rotate parent left. |
750 |
sibling.color = BLACK; |
sibling.color = BLACK; |
751 |
node.parent.color = RED; |
parent.color = RED; |
752 |
rotateLeft(node.parent); |
rotateLeft(parent); |
753 |
sibling = node.parent.right; |
sibling = parent.right; |
754 |
} |
} |
755 |
|
|
756 |
if (sibling.left.color == BLACK && sibling.right.color == BLACK) |
if (sibling.left.color == BLACK && sibling.right.color == BLACK) |
757 |
{ |
{ |
758 |
// Case 2: Sibling has no red children. |
// Case 2: Sibling has no red children. |
759 |
sibling.color = RED; |
// Recolor sibling, and move to parent. |
760 |
// Black height has been decreased, so move up the tree and |
sibling.color = RED; |
761 |
// repeat. |
node = parent; |
762 |
node = node.parent; |
parent = parent.parent; |
763 |
} |
} |
764 |
else |
else |
765 |
{ |
{ |
766 |
if (sibling.right.color == BLACK) |
if (sibling.right.color == BLACK) |
767 |
{ |
{ |
768 |
// Case 3: Sibling has red left child. |
// Case 3: Sibling has red left child. |
769 |
sibling.left.color = BLACK; |
// Recolor sibling and left child, rotate sibling right. |
770 |
sibling.color = RED; |
sibling.left.color = BLACK; |
771 |
|
sibling.color = RED; |
772 |
rotateRight(sibling); |
rotateRight(sibling); |
773 |
sibling = node.parent.right; |
sibling = parent.right; |
774 |
} |
} |
775 |
|
// Case 4: Sibling has red right child. Recolor sibling, |
776 |
// Case 4: Sibling has red right child. |
// right child, and parent, and rotate parent left. |
777 |
sibling.color = sibling.parent.color; |
sibling.color = parent.color; |
778 |
sibling.parent.color = BLACK; |
parent.color = BLACK; |
779 |
sibling.right.color = BLACK; |
sibling.right.color = BLACK; |
780 |
rotateLeft(node.parent); |
rotateLeft(parent); |
781 |
node = root; // Finished. |
node = root; // Finished. |
782 |
} |
} |
783 |
} |
} |
784 |
else |
else |
785 |
{ |
{ |
786 |
// Symmetric "mirror" of left-side case. |
// Symmetric "mirror" of left-side case. |
787 |
Node sibling = node.parent.left; |
Node sibling = parent.left; |
788 |
if (sibling.color == RED) |
// if (sibling == nil) |
789 |
{ |
// throw new InternalError(); |
790 |
|
if (sibling.color == RED) |
791 |
|
{ |
792 |
|
// Case 1: Sibling is red. |
793 |
|
// Recolor sibling and parent, and rotate parent right. |
794 |
sibling.color = BLACK; |
sibling.color = BLACK; |
795 |
node.parent.color = RED; |
parent.color = RED; |
796 |
rotateRight(node.parent); |
rotateRight(parent); |
797 |
sibling = node.parent.left; |
sibling = parent.left; |
798 |
} |
} |
799 |
|
|
800 |
if (sibling.left.color == BLACK && sibling.right.color == BLACK) |
if (sibling.right.color == BLACK && sibling.left.color == BLACK) |
801 |
{ |
{ |
802 |
sibling.color = RED; |
// Case 2: Sibling has no red children. |
803 |
node = node.parent; |
// Recolor sibling, and move to parent. |
804 |
|
sibling.color = RED; |
805 |
|
node = parent; |
806 |
|
parent = parent.parent; |
807 |
} |
} |
808 |
else |
else |
809 |
{ |
{ |
810 |
if (sibling.left.color == BLACK) |
if (sibling.left.color == BLACK) |
811 |
{ |
{ |
812 |
sibling.right.color = BLACK; |
// Case 3: Sibling has red right child. |
813 |
sibling.color = RED; |
// Recolor sibling and right child, rotate sibling left. |
814 |
|
sibling.right.color = BLACK; |
815 |
|
sibling.color = RED; |
816 |
rotateLeft(sibling); |
rotateLeft(sibling); |
817 |
sibling = node.parent.left; |
sibling = parent.left; |
818 |
} |
} |
819 |
|
// Case 4: Sibling has red left child. Recolor sibling, |
820 |
sibling.color = sibling.parent.color; |
// left child, and parent, and rotate parent right. |
821 |
sibling.parent.color = BLACK; |
sibling.color = parent.color; |
822 |
sibling.left.color = BLACK; |
parent.color = BLACK; |
823 |
rotateRight(node.parent); |
sibling.left.color = BLACK; |
824 |
node = root; |
rotateRight(parent); |
825 |
} |
node = root; // Finished. |
826 |
} |
} |
827 |
|
} |
828 |
} |
} |
829 |
node.color = BLACK; |
node.color = BLACK; |
830 |
} |
} |
831 |
|
|
832 |
public SortedMap subMap(Object fromKey, Object toKey) |
/** |
833 |
|
* Construct a perfectly balanced tree consisting of n "blank" nodes. This |
834 |
|
* permits a tree to be generated from pre-sorted input in linear time. |
835 |
|
* |
836 |
|
* @param count the number of blank nodes, non-negative |
837 |
|
*/ |
838 |
|
private void fabricateTree(final int count) |
839 |
{ |
{ |
840 |
if (compare(fromKey, toKey) <= 0) |
if (count == 0) |
841 |
return new SubMap(fromKey, toKey); |
return; |
|
else |
|
|
throw new IllegalArgumentException("fromKey > toKey"); |
|
|
} |
|
842 |
|
|
843 |
public SortedMap headMap(Object toKey) |
// We color every row of nodes black, except for the overflow nodes. |
844 |
{ |
// I believe that this is the optimal arrangement. We construct the tree |
845 |
return new SubMap(nil, toKey); |
// in place by temporarily linking each node to the next node in the row, |
846 |
|
// then updating those links to the children when working on the next row. |
847 |
|
|
848 |
|
// Make the root node. |
849 |
|
root = new Node(null, null, BLACK); |
850 |
|
size = count; |
851 |
|
Node row = root; |
852 |
|
int rowsize; |
853 |
|
|
854 |
|
// Fill each row that is completely full of nodes. |
855 |
|
for (rowsize = 2; rowsize + rowsize < count; rowsize <<= 1) |
856 |
|
{ |
857 |
|
Node parent = row; |
858 |
|
Node last = null; |
859 |
|
for (int i = 0; i < rowsize; i += 2) |
860 |
|
{ |
861 |
|
Node left = new Node(null, null, BLACK); |
862 |
|
Node right = new Node(null, null, BLACK); |
863 |
|
left.parent = parent; |
864 |
|
left.right = right; |
865 |
|
right.parent = parent; |
866 |
|
parent.left = left; |
867 |
|
Node next = parent.right; |
868 |
|
parent.right = right; |
869 |
|
parent = next; |
870 |
|
if (last != null) |
871 |
|
last.right = left; |
872 |
|
last = right; |
873 |
|
} |
874 |
|
row = row.left; |
875 |
|
} |
876 |
|
|
877 |
|
// Now do the partial final row in red. |
878 |
|
int overflow = count - rowsize; |
879 |
|
Node parent = row; |
880 |
|
int i; |
881 |
|
for (i = 0; i < overflow; i += 2) |
882 |
|
{ |
883 |
|
Node left = new Node(null, null, RED); |
884 |
|
Node right = new Node(null, null, RED); |
885 |
|
left.parent = parent; |
886 |
|
right.parent = parent; |
887 |
|
parent.left = left; |
888 |
|
Node next = parent.right; |
889 |
|
parent.right = right; |
890 |
|
parent = next; |
891 |
|
} |
892 |
|
// Add a lone left node if necessary. |
893 |
|
if (i - overflow == 0) |
894 |
|
{ |
895 |
|
Node left = new Node(null, null, RED); |
896 |
|
left.parent = parent; |
897 |
|
parent.left = left; |
898 |
|
parent = parent.right; |
899 |
|
left.parent.right = nil; |
900 |
|
} |
901 |
|
// Unlink the remaining nodes of the previous row. |
902 |
|
while (parent != nil) |
903 |
|
{ |
904 |
|
Node next = parent.right; |
905 |
|
parent.right = nil; |
906 |
|
parent = next; |
907 |
|
} |
908 |
} |
} |
909 |
|
|
910 |
public SortedMap tailMap(Object fromKey) |
/** |
911 |
|
* Returns the first sorted node in the map, or nil if empty. Package |
912 |
|
* visible for use by nested classes. |
913 |
|
* |
914 |
|
* @return the first node |
915 |
|
*/ |
916 |
|
final Node firstNode() |
917 |
{ |
{ |
918 |
return new SubMap(fromKey, nil); |
// Exploit fact that nil.left == nil. |
919 |
|
Node node = root; |
920 |
|
while (node.left != nil) |
921 |
|
node = node.left; |
922 |
|
return node; |
923 |
} |
} |
924 |
|
|
925 |
/** Returns a "collection view" (or "bag view") of this TreeMap's values. */ |
/** |
926 |
public Collection values() |
* Return the TreeMap.Node associated with key, or the nil node if no such |
927 |
|
* node exists in the tree. Package visible for use by nested classes. |
928 |
|
* |
929 |
|
* @param key the key to search for |
930 |
|
* @return the node where the key is found, or nil |
931 |
|
*/ |
932 |
|
final Node getNode(Object key) |
933 |
{ |
{ |
934 |
// We don't bother overriding many of the optional methods, as doing so |
Node current = root; |
935 |
// wouldn't provide any significant performance advantage. |
while (current != nil) |
|
return new AbstractCollection() |
|
|
{ |
|
|
public int size() |
|
|
{ |
|
|
return size; |
|
|
} |
|
|
|
|
|
public Iterator iterator() |
|
|
{ |
|
|
return new TreeIterator(TreeIterator.VALUES); |
|
|
} |
|
|
|
|
|
public void clear() |
|
936 |
{ |
{ |
937 |
TreeMap.this.clear(); |
int comparison = compare(key, current.key); |
938 |
|
if (comparison > 0) |
939 |
|
current = current.right; |
940 |
|
else if (comparison < 0) |
941 |
|
current = current.left; |
942 |
|
else |
943 |
|
return current; |
944 |
} |
} |
945 |
}; |
return current; |
946 |
} |
} |
947 |
|
|
948 |
// Find the "highest" node which is < key. If key is nil, return last node. |
/** |
949 |
// Note that highestLessThan is exclusive (it won't return a key which is |
* Find the "highest" node which is < key. If key is nil, return last |
950 |
// equal to "key"), while lowestGreaterThan is inclusive, in order to be |
* node. Package visible for use by nested classes. |
951 |
// consistent with the semantics of subMap(). |
* |
952 |
private Node highestLessThan(Object key) |
* @param key the upper bound, exclusive |
953 |
|
* @return the previous node |
954 |
|
*/ |
955 |
|
final Node highestLessThan(Object key) |
956 |
{ |
{ |
957 |
if (key == nil) |
if (key == nil) |
958 |
return lastNode(); |
return lastNode(); |
959 |
|
|
960 |
Node last = nil; |
Node last = nil; |
961 |
Node current = root; |
Node current = root; |
962 |
int comparison = 0; |
int comparison = 0; |
965 |
{ |
{ |
966 |
last = current; |
last = current; |
967 |
comparison = compare(key, current.key); |
comparison = compare(key, current.key); |
968 |
if (comparison > 0) |
if (comparison > 0) |
969 |
current = current.right; |
current = current.right; |
970 |
else if (comparison < 0) |
else if (comparison < 0) |
971 |
current = current.left; |
current = current.left; |
972 |
else /* Exact match. */ |
else // Exact match. |
973 |
return predecessor(last); |
return predecessor(last); |
974 |
} |
} |
975 |
if (comparison <= 0) |
return comparison <= 0 ? predecessor(last) : last; |
976 |
return predecessor(last); |
} |
977 |
else |
|
978 |
return last; |
/** |
979 |
|
* Maintain red-black balance after inserting a new node. |
980 |
|
* |
981 |
|
* @param n the newly inserted node |
982 |
|
*/ |
983 |
|
private void insertFixup(Node n) |
984 |
|
{ |
985 |
|
// Only need to rebalance when parent is a RED node, and while at least |
986 |
|
// 2 levels deep into the tree (ie: node has a grandparent). Remember |
987 |
|
// that nil.color == BLACK. |
988 |
|
while (n.parent.color == RED && n.parent.parent != nil) |
989 |
|
{ |
990 |
|
if (n.parent == n.parent.parent.left) |
991 |
|
{ |
992 |
|
Node uncle = n.parent.parent.right; |
993 |
|
// Uncle may be nil, in which case it is BLACK. |
994 |
|
if (uncle.color == RED) |
995 |
|
{ |
996 |
|
// Case 1. Uncle is RED: Change colors of parent, uncle, |
997 |
|
// and grandparent, and move n to grandparent. |
998 |
|
n.parent.color = BLACK; |
999 |
|
uncle.color = BLACK; |
1000 |
|
uncle.parent.color = RED; |
1001 |
|
n = uncle.parent; |
1002 |
|
} |
1003 |
|
else |
1004 |
|
{ |
1005 |
|
if (n == n.parent.right) |
1006 |
|
{ |
1007 |
|
// Case 2. Uncle is BLACK and x is right child. |
1008 |
|
// Move n to parent, and rotate n left. |
1009 |
|
n = n.parent; |
1010 |
|
rotateLeft(n); |
1011 |
|
} |
1012 |
|
// Case 3. Uncle is BLACK and x is left child. |
1013 |
|
// Recolor parent, grandparent, and rotate grandparent right. |
1014 |
|
n.parent.color = BLACK; |
1015 |
|
n.parent.parent.color = RED; |
1016 |
|
rotateRight(n.parent.parent); |
1017 |
|
} |
1018 |
|
} |
1019 |
|
else |
1020 |
|
{ |
1021 |
|
// Mirror image of above code. |
1022 |
|
Node uncle = n.parent.parent.left; |
1023 |
|
// Uncle may be nil, in which case it is BLACK. |
1024 |
|
if (uncle.color == RED) |
1025 |
|
{ |
1026 |
|
// Case 1. Uncle is RED: Change colors of parent, uncle, |
1027 |
|
// and grandparent, and move n to grandparent. |
1028 |
|
n.parent.color = BLACK; |
1029 |
|
uncle.color = BLACK; |
1030 |
|
uncle.parent.color = RED; |
1031 |
|
n = uncle.parent; |
1032 |
|
} |
1033 |
|
else |
1034 |
|
{ |
1035 |
|
if (n == n.parent.left) |
1036 |
|
{ |
1037 |
|
// Case 2. Uncle is BLACK and x is left child. |
1038 |
|
// Move n to parent, and rotate n right. |
1039 |
|
n = n.parent; |
1040 |
|
rotateRight(n); |
1041 |
|
} |
1042 |
|
// Case 3. Uncle is BLACK and x is right child. |
1043 |
|
// Recolor parent, grandparent, and rotate grandparent left. |
1044 |
|
n.parent.color = BLACK; |
1045 |
|
n.parent.parent.color = RED; |
1046 |
|
rotateLeft(n.parent.parent); |
1047 |
|
} |
1048 |
|
} |
1049 |
|
} |
1050 |
|
root.color = BLACK; |
1051 |
} |
} |
1052 |
|
|
1053 |
// Find the "lowest" node which is >= key. If key is nil, return first node. |
/** |
1054 |
private Node lowestGreaterThan(Object key) |
* Returns the last sorted node in the map, or nil if empty. |
1055 |
|
* |
1056 |
|
* @return the last node |
1057 |
|
*/ |
1058 |
|
private Node lastNode() |
1059 |
|
{ |
1060 |
|
// Exploit fact that nil.right == nil. |
1061 |
|
Node node = root; |
1062 |
|
while (node.right != nil) |
1063 |
|
node = node.right; |
1064 |
|
return node; |
1065 |
|
} |
1066 |
|
|
1067 |
|
/** |
1068 |
|
* Find the "lowest" node which is >= key. If key is nil, return either |
1069 |
|
* nil or the first node, depending on the parameter first. |
1070 |
|
* Package visible for use by nested classes. |
1071 |
|
* |
1072 |
|
* @param key the lower bound, inclusive |
1073 |
|
* @param first true to return the first element instead of nil for nil key |
1074 |
|
* @return the next node |
1075 |
|
*/ |
1076 |
|
final Node lowestGreaterThan(Object key, boolean first) |
1077 |
{ |
{ |
1078 |
if (key == nil) |
if (key == nil) |
1079 |
return firstNode(); |
return first ? firstNode() : nil; |
1080 |
|
|
1081 |
Node last = nil; |
Node last = nil; |
1082 |
Node current = root; |
Node current = root; |
1086 |
{ |
{ |
1087 |
last = current; |
last = current; |
1088 |
comparison = compare(key, current.key); |
comparison = compare(key, current.key); |
1089 |
if (comparison > 0) |
if (comparison > 0) |
1090 |
current = current.right; |
current = current.right; |
1091 |
else if (comparison < 0) |
else if (comparison < 0) |
1092 |
current = current.left; |
current = current.left; |
1093 |
else |
else |
1094 |
return current; |
return current; |
1095 |
} |
} |
1096 |
if (comparison > 0) |
return comparison > 0 ? successor(last) : last; |
1097 |
return successor(last); |
} |
|
else |
|
|
return last; |
|
|
} |
|
1098 |
|
|
1099 |
private void writeObject(ObjectOutputStream out) throws IOException |
/** |
1100 |
|
* Return the node preceding the given one, or nil if there isn't one. |
1101 |
|
* |
1102 |
|
* @param node the current node, not nil |
1103 |
|
* @return the prior node in sorted order |
1104 |
|
*/ |
1105 |
|
private Node predecessor(Node node) |
1106 |
{ |
{ |
1107 |
out.defaultWriteObject(); |
if (node.left != nil) |
1108 |
|
{ |
1109 |
|
node = node.left; |
1110 |
|
while (node.right != nil) |
1111 |
|
node = node.right; |
1112 |
|
return node; |
1113 |
|
} |
1114 |
|
|
1115 |
Node node = firstNode(); |
Node parent = node.parent; |
1116 |
out.writeInt(size); |
// Exploit fact that nil.left == nil and node is non-nil. |
1117 |
|
while (node == parent.left) |
|
while (node != nil) |
|
1118 |
{ |
{ |
1119 |
out.writeObject(node.key); |
node = parent; |
1120 |
out.writeObject(node.value); |
parent = node.parent; |
|
node = successor(node); |
|
1121 |
} |
} |
1122 |
|
return parent; |
1123 |
} |
} |
1124 |
|
|
1125 |
private void readObject(ObjectInputStream in) |
/** |
1126 |
|
* Construct a tree from sorted keys in linear time. Package visible for |
1127 |
|
* use by TreeSet. |
1128 |
|
* |
1129 |
|
* @param s the stream to read from |
1130 |
|
* @param count the number of keys to read |
1131 |
|
* @param readValue true to read values, false to insert "" as the value |
1132 |
|
* @throws ClassNotFoundException if the underlying stream fails |
1133 |
|
* @throws IOException if the underlying stream fails |
1134 |
|
* @see #readObject(ObjectInputStream) |
1135 |
|
* @see TreeSet#readObject(ObjectInputStream) |
1136 |
|
*/ |
1137 |
|
final void putFromObjStream(ObjectInputStream s, int count, |
1138 |
|
boolean readValues) |
1139 |
throws IOException, ClassNotFoundException |
throws IOException, ClassNotFoundException |
1140 |
{ |
{ |
1141 |
in.defaultReadObject(); |
fabricateTree(count); |
1142 |
int size = in.readInt(); |
Node node = firstNode(); |
|
putFromObjStream(in, size, true); |
|
|
} |
|
1143 |
|
|
1144 |
private int compare(Object o1, Object o2) |
while (--count >= 0) |
1145 |
{ |
{ |
1146 |
if (comparator == null) |
node.key = s.readObject(); |
1147 |
return ((Comparable) o1).compareTo(o2); |
node.value = readValues ? s.readObject() : ""; |
1148 |
else |
node = successor(node); |
1149 |
return comparator.compare(o1, o2); |
} |
1150 |
} |
} |
1151 |
|
|
1152 |
/* Return the node following Node, or nil if there isn't one. */ |
/** |
1153 |
private Node successor(Node node) |
* Construct a tree from sorted keys in linear time, with values of "". |
1154 |
|
* Package visible for use by TreeSet. |
1155 |
|
* |
1156 |
|
* @param keys the iterator over the sorted keys |
1157 |
|
* @param count the number of nodes to insert |
1158 |
|
* @see TreeSet#TreeSet(SortedSet) |
1159 |
|
*/ |
1160 |
|
final void putKeysLinear(Iterator keys, int count) |
1161 |
{ |
{ |
1162 |
if (node.right != nil) |
fabricateTree(count); |
1163 |
{ |
Node node = firstNode(); |
|
node = node.right; |
|
|
while (node.left != nil) |
|
|
node = node.left; |
|
|
return node; |
|
|
} |
|
1164 |
|
|
1165 |
Node parent = node.parent; |
while (--count >= 0) |
|
while (parent != nil && node == parent.right) |
|
1166 |
{ |
{ |
1167 |
node = parent; |
node.key = keys.next(); |
1168 |
parent = parent.parent; |
node.value = ""; |
1169 |
|
node = successor(node); |
1170 |
} |
} |
|
return parent; |
|
1171 |
} |
} |
1172 |
|
|
1173 |
/* Return the node preceeding Node, or nil if there isn't one. */ |
/** |
1174 |
private Node predecessor(Node node) |
* Deserializes this object from the given stream. |
1175 |
|
* |
1176 |
|
* @param s the stream to read from |
1177 |
|
* @throws ClassNotFoundException if the underlying stream fails |
1178 |
|
* @throws IOException if the underlying stream fails |
1179 |
|
* @serialData the <i>size</i> (int), followed by key (Object) and value |
1180 |
|
* (Object) pairs in sorted order |
1181 |
|
*/ |
1182 |
|
private void readObject(ObjectInputStream s) |
1183 |
|
throws IOException, ClassNotFoundException |
1184 |
{ |
{ |
1185 |
if (node.left != nil) |
s.defaultReadObject(); |
1186 |
|
int size = s.readInt(); |
1187 |
|
putFromObjStream(s, size, true); |
1188 |
|
} |
1189 |
|
|
1190 |
|
/** |
1191 |
|
* Remove node from tree. This will increment modCount and decrement size. |
1192 |
|
* Node must exist in the tree. Package visible for use by nested classes. |
1193 |
|
* |
1194 |
|
* @param node the node to remove |
1195 |
|
*/ |
1196 |
|
final void removeNode(Node node) |
1197 |
|
{ |
1198 |
|
Node splice; |
1199 |
|
Node child; |
1200 |
|
|
1201 |
|
modCount++; |
1202 |
|
size--; |
1203 |
|
|
1204 |
|
// Find splice, the node at the position to actually remove from the tree. |
1205 |
|
if (node.left == nil) |
1206 |
{ |
{ |
1207 |
node = node.left; |
// Node to be deleted has 0 or 1 children. |
1208 |
while (node.right != nil) |
splice = node; |
1209 |
node = node.right; |
child = node.right; |
|
return node; |
|
1210 |
} |
} |
1211 |
|
else if (node.right == nil) |
|
Node parent = node.parent; |
|
|
while (parent != nil && node == parent.left) |
|
1212 |
{ |
{ |
1213 |
node = parent; |
// Node to be deleted has 0 children. |
1214 |
parent = parent.parent; |
splice = node; |
1215 |
|
child = nil; |
1216 |
} |
} |
1217 |
return parent; |
else |
1218 |
|
{ |
1219 |
|
// Node has 2 children. Splice is node's predecessor, and we swap |
1220 |
|
// its contents into node. |
1221 |
|
splice = node.left; |
1222 |
|
while (splice.right != nil) |
1223 |
|
splice = splice.right; |
1224 |
|
child = splice.left; |
1225 |
|
node.key = splice.key; |
1226 |
|
node.value = splice.value; |
1227 |
|
} |
1228 |
|
|
1229 |
|
// Unlink splice from the tree. |
1230 |
|
Node parent = splice.parent; |
1231 |
|
if (child != nil) |
1232 |
|
child.parent = parent; |
1233 |
|
if (parent == nil) |
1234 |
|
{ |
1235 |
|
// Special case for 0 or 1 node remaining. |
1236 |
|
root = child; |
1237 |
|
return; |
1238 |
|
} |
1239 |
|
if (splice == parent.left) |
1240 |
|
parent.left = child; |
1241 |
|
else |
1242 |
|
parent.right = child; |
1243 |
|
|
1244 |
|
if (splice.color == BLACK) |
1245 |
|
deleteFixup(child, parent); |
1246 |
} |
} |
1247 |
|
|
1248 |
/** Rotate node n to the left. */ |
/** |
1249 |
|
* Rotate node n to the left. |
1250 |
|
* |
1251 |
|
* @param node the node to rotate |
1252 |
|
*/ |
1253 |
private void rotateLeft(Node node) |
private void rotateLeft(Node node) |
1254 |
{ |
{ |
1255 |
Node child = node.right; |
Node child = node.right; |
1256 |
|
// if (node == nil || child == nil) |
1257 |
|
// throw new InternalError(); |
1258 |
|
|
1259 |
// Establish node.right link. |
// Establish node.right link. |
1260 |
node.right = child.left; |
node.right = child.left; |
1261 |
if (child.left != nil) |
if (child.left != nil) |
1266 |
if (node.parent != nil) |
if (node.parent != nil) |
1267 |
{ |
{ |
1268 |
if (node == node.parent.left) |
if (node == node.parent.left) |
1269 |
node.parent.left = child; |
node.parent.left = child; |
1270 |
else |
else |
1271 |
node.parent.right = child; |
node.parent.right = child; |
1272 |
} |
} |
1273 |
else |
else |
1274 |
root = child; |
root = child; |
1275 |
|
|
1276 |
// Link n and child. |
// Link n and child. |
1277 |
child.left = node; |
child.left = node; |
1278 |
if (node != nil) |
node.parent = child; |
|
node.parent = child; |
|
1279 |
} |
} |
1280 |
|
|
1281 |
/** Rotate node n to the right. */ |
/** |
1282 |
|
* Rotate node n to the right. |
1283 |
|
* |
1284 |
|
* @param node the node to rotate |
1285 |
|
*/ |
1286 |
private void rotateRight(Node node) |
private void rotateRight(Node node) |
1287 |
{ |
{ |
1288 |
Node child = node.left; |
Node child = node.left; |
1289 |
|
// if (node == nil || child == nil) |
1290 |
|
// throw new InternalError(); |
1291 |
|
|
1292 |
// Establish node.left link. |
// Establish node.left link. |
1293 |
node.left = child.right; |
node.left = child.right; |
1294 |
if (child.right != nil) |
if (child.right != nil) |
1295 |
child.right.parent = node; |
child.right.parent = node; |
1296 |
|
|
1297 |
// Establish child->parent link. |
// Establish child->parent link. |
1298 |
child.parent = node.parent; |
child.parent = node.parent; |
1299 |
if (node.parent != nil) |
if (node.parent != nil) |
1300 |
{ |
{ |
1301 |
if (node == node.parent.right) |
if (node == node.parent.right) |
1302 |
node.parent.right = child; |
node.parent.right = child; |
1303 |
else |
else |
1304 |
node.parent.left = child; |
node.parent.left = child; |
1305 |
} |
} |
1306 |
else |
else |
1307 |
root = child; |
root = child; |
1308 |
|
|
1309 |
// Link n and child. |
// Link n and child. |
1310 |
child.right = node; |
child.right = node; |
1311 |
if (node != nil) |
node.parent = child; |
|
node.parent = child; |
|
1312 |
} |
} |
1313 |
|
|
1314 |
/* Construct a tree from sorted keys in linear time. This is used to |
/** |
1315 |
implement TreeSet's SortedSet constructor. */ |
* Return the node following the given one, or nil if there isn't one. |
1316 |
void putKeysLinear(Iterator keys, int count) |
* Package visible for use by nested classes. |
1317 |
|
* |
1318 |
|
* @param node the current node, not nil |
1319 |
|
* @return the next node in sorted order |
1320 |
|
*/ |
1321 |
|
final Node successor(Node node) |
1322 |
{ |
{ |
1323 |
fabricateTree(count); |
if (node.right != nil) |
|
Node node = firstNode(); |
|
|
|
|
|
for (int i = 0; i < count; i++) |
|
1324 |
{ |
{ |
1325 |
node.key = keys.next(); |
node = node.right; |
1326 |
node.value = Boolean.TRUE; |
while (node.left != nil) |
1327 |
node = successor(node); |
node = node.left; |
1328 |
|
return node; |
1329 |
} |
} |
|
} |
|
|
|
|
|
/* As above, but load keys from an ObjectInputStream. Used by readObject() |
|
|
methods. If "readValues" is set, entry values will also be read from the |
|
|
stream. If not, only keys will be read. */ |
|
|
void putFromObjStream(ObjectInputStream in, int count, boolean readValues) |
|
|
throws IOException, ClassNotFoundException |
|
|
{ |
|
|
fabricateTree(count); |
|
|
Node node = firstNode(); |
|
|
|
|
|
for (int i = 0; i < count; i++) |
|
|
{ |
|
|
node.key = in.readObject(); |
|
|
if (readValues) |
|
|
node.value = in.readObject(); |
|
|
else |
|
|
node.value = Boolean.TRUE; |
|
|
node = successor(node); |
|
|
} |
|
|
} |
|
|
|
|
|
/* Construct a perfectly balanced tree consisting of n "blank" nodes. |
|
|
This permits a tree to be generated from pre-sorted input in linear |
|
|
time. */ |
|
|
private void fabricateTree(int count) |
|
|
{ |
|
|
if (count == 0) |
|
|
return; |
|
|
// Calculate the (maximum) depth of the perfectly balanced tree. |
|
|
double ddepth = (Math.log (count + 1) / Math.log (2)); |
|
|
int maxdepth = (int) Math.ceil (ddepth); |
|
|
|
|
|
// The number of nodes which can fit in a perfectly-balanced tree of |
|
|
// height "depth - 1". |
|
|
int max = (int) Math.pow (2, maxdepth - 1) - 1; |
|
|
|
|
|
// Number of nodes which spill over into the deepest row of the tree. |
|
|
int overflow = (int) count - max; |
|
|
|
|
|
size = count; |
|
|
// Make the root node. |
|
|
root = new Node(null, null); |
|
|
root.parent = nil; |
|
|
root.left = nil; |
|
|
root.right = nil; |
|
|
|
|
|
Node row = root; |
|
|
for (int depth = 2; depth <= maxdepth; depth++) // each row |
|
|
{ |
|
|
// Number of nodes at this depth |
|
|
int rowcap = (int) Math.pow (2, depth - 1); |
|
|
Node parent = row; |
|
|
Node last = null; |
|
|
|
|
|
// Actual number of nodes to create in this row |
|
|
int rowsize; |
|
|
if (depth == maxdepth) |
|
|
rowsize = overflow; |
|
|
else |
|
|
rowsize = rowcap; |
|
|
|
|
|
// The bottom most row of nodes is coloured red, as is every second row |
|
|
// going up, except the root node (row 1). I'm not sure if this is the |
|
|
// optimal configuration for the tree, but it seems logical enough. |
|
|
// We just need to honour the black-height and red-parent rules here. |
|
|
boolean colorRowRed = (depth % 2 == maxdepth % 2); |
|
|
|
|
|
int i; |
|
|
for (i = 1; i <= rowsize; i++) // each node in row |
|
|
{ |
|
|
Node node = new Node(null, null); |
|
|
node.parent = parent; |
|
|
if (i % 2 == 1) |
|
|
parent.left = node; |
|
|
else |
|
|
{ |
|
|
Node nextparent = parent.right; |
|
|
parent.right = node; |
|
|
parent = nextparent; |
|
|
} |
|
|
|
|
|
// We use the "right" link to maintain a chain of nodes in |
|
|
// each row until the parent->child links are established. |
|
|
if (last != null) |
|
|
last.right = node; |
|
|
last = node; |
|
|
|
|
|
if (colorRowRed) |
|
|
node.color = RED; |
|
|
|
|
|
if (i == 1) |
|
|
row = node; |
|
|
} |
|
|
|
|
|
// Set nil child pointers on leaf nodes. |
|
|
if (depth == maxdepth) |
|
|
{ |
|
|
// leaf nodes at maxdepth-1. |
|
|
if (parent != null) |
|
|
{ |
|
|
if (i % 2 == 0) |
|
|
{ |
|
|
// Current "parent" has "left" set already. |
|
|
Node next = parent.right; |
|
|
parent.right = nil; |
|
|
parent = next; |
|
|
} |
|
|
while (parent != null) |
|
|
{ |
|
|
parent.left = nil; |
|
|
Node next = parent.right; |
|
|
parent.right = nil; |
|
|
parent = next; |
|
|
} |
|
|
} |
|
|
// leaf nodes at maxdepth. |
|
|
Node node = row; |
|
|
Node next; |
|
|
while (node != null) |
|
|
{ |
|
|
node.left = nil; |
|
|
next = node.right; |
|
|
node.right = nil; |
|
|
node = next; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
private class VerifyResult |
|
|
{ |
|
|
int count; // Total number of nodes. |
|
|
int black; // Black height/depth. |
|
|
int maxdepth; // Maximum depth of branch. |
|
|
} |
|
1330 |
|
|
1331 |
/* Check that red-black properties are consistent for the tree. */ |
Node parent = node.parent; |
1332 |
private void verifyTree() |
// Exploit fact that nil.right == nil and node is non-nil. |
1333 |
{ |
while (node == parent.right) |
|
if (root == nil) |
|
1334 |
{ |
{ |
1335 |
System.err.println ("Verify: empty tree"); |
node = parent; |
1336 |
if (size != 0) |
parent = parent.parent; |
1337 |
verifyError (this, "no root node but size=" + size); |
} |
1338 |
return; |
return parent; |
|
} |
|
|
VerifyResult vr = verifySub (root); |
|
|
if (vr.count != size) |
|
|
{ |
|
|
verifyError (this, "Tree size not consistent with actual nodes counted. " |
|
|
+ "counted " + vr.count + ", size=" + size); |
|
|
System.exit(1); |
|
|
} |
|
|
System.err.println ("Verify: " + vr.count + " nodes, black height=" + vr.black |
|
|
+ ", maxdepth=" + vr.maxdepth); |
|
|
} |
|
|
|
|
|
/* Recursive call to check that rbtree rules hold. Returns total node count |
|
|
and black height of the given branch. */ |
|
|
private VerifyResult verifySub(Node n) |
|
|
{ |
|
|
VerifyResult vr1 = null; |
|
|
VerifyResult vr2 = null; |
|
|
|
|
|
if (n.left == nil && n.right == nil) |
|
|
{ |
|
|
// leaf node |
|
|
VerifyResult r = new VerifyResult(); |
|
|
r.black = (n.color == BLACK ? 1 : 0); |
|
|
r.count = 1; |
|
|
r.maxdepth = 1; |
|
|
return r; |
|
|
} |
|
|
|
|
|
if (n.left != nil) |
|
|
{ |
|
|
if (n.left.parent != n) |
|
|
verifyError(n.left, "Node's parent link does not point to " + n); |
|
|
|
|
|
if (n.color == RED && n.left.color == RED) |
|
|
verifyError(n, "Red node has red left child"); |
|
|
|
|
|
vr1 = verifySub (n.left); |
|
|
if (n.right == nil) |
|
|
{ |
|
|
if (n.color == BLACK) |
|
|
vr1.black++; |
|
|
vr1.count++; |
|
|
vr1.maxdepth++; |
|
|
return vr1; |
|
|
} |
|
|
} |
|
|
|
|
|
if (n.right != nil) |
|
|
{ |
|
|
if (n.right.parent != n) |
|
|
verifyError(n.right, "Node's parent link does not point to " + n); |
|
|
|
|
|
if (n.color == RED && n.right.color == RED) |
|
|
verifyError(n, "Red node has red right child"); |
|
|
|
|
|
vr2 = verifySub (n.right); |
|
|
if (n.left == nil) |
|
|
{ |
|
|
if (n.color == BLACK) |
|
|
vr2.black++; |
|
|
vr2.count++; |
|
|
vr2.maxdepth++; |
|
|
return vr2; |
|
|
} |
|
|
} |
|
|
|
|
|
if (vr1.black != vr2.black) |
|
|
verifyError (n, "Black heights: " + vr1.black + "," + vr2.black + " don't match."); |
|
|
vr1.count += vr2.count + 1; |
|
|
vr1.maxdepth = Math.max(vr1.maxdepth, vr2.maxdepth) + 1; |
|
|
if (n.color == BLACK) |
|
|
vr1.black++; |
|
|
return vr1; |
|
1339 |
} |
} |
1340 |
|
|
1341 |
private void verifyError (Object obj, String msg) |
/** |
1342 |
|
* Serializes this object to the given stream. |
1343 |
|
* |
1344 |
|
* @param s the stream to write to |
1345 |
|
* @throws IOException if the underlying stream fails |
1346 |
|
* @serialData the <i>size</i> (int), followed by key (Object) and value |
1347 |
|
* (Object) pairs in sorted order |
1348 |
|
*/ |
1349 |
|
private void writeObject(ObjectOutputStream s) throws IOException |
1350 |
{ |
{ |
1351 |
System.err.print ("Verify error: "); |
s.defaultWriteObject(); |
1352 |
try |
|
1353 |
{ |
Node node = firstNode(); |
1354 |
System.err.print (obj); |
s.writeInt(size); |
1355 |
} |
while (node != nil) |
|
catch (Exception x) |
|
1356 |
{ |
{ |
1357 |
System.err.print ("(error printing obj): " + x); |
s.writeObject(node.key); |
1358 |
|
s.writeObject(node.value); |
1359 |
|
node = successor(node); |
1360 |
} |
} |
|
System.err.println(); |
|
|
System.err.println (msg); |
|
|
Thread.dumpStack(); |
|
|
System.exit(1); |
|
1361 |
} |
} |
1362 |
|
|
1363 |
/** |
/** |
1364 |
* Iterate over HashMap's entries. |
* Iterate over HashMap's entries. This implementation is parameterized |
1365 |
* This implementation is parameterized to give a sequential view of |
* to give a sequential view of keys, values, or entries. |
1366 |
* keys, values, or entries. |
* |
1367 |
*/ |
* @author Eric Blake <ebb9@email.byu.edu> |
1368 |
class TreeIterator implements Iterator |
*/ |
1369 |
{ |
private final class TreeIterator implements Iterator |
1370 |
static final int ENTRIES = 0, |
{ |
1371 |
KEYS = 1, |
/** |
1372 |
VALUES = 2; |
* The type of this Iterator: {@link #KEYS}, {@link #VALUES}, |
1373 |
|
* or {@link #ENTRIES}. |
1374 |
// the type of this Iterator: KEYS, VALUES, or ENTRIES. |
*/ |
1375 |
int type; |
private final int type; |
1376 |
// the number of modifications to the backing Map that we know about. |
/** The number of modifications to the backing Map that we know about. */ |
1377 |
int knownMod = TreeMap.this.modCount; |
private int knownMod = modCount; |
1378 |
// The last Entry returned by a next() call. |
/** The last Entry returned by a next() call. */ |
1379 |
Node last; |
private Node last; |
1380 |
// The next entry that should be returned by next(). |
/** The next entry that should be returned by next(). */ |
1381 |
Node next; |
private Node next; |
1382 |
// The last node visible to this iterator. This is used when iterating |
/** |
1383 |
// on a SubMap. |
* The last node visible to this iterator. This is used when iterating |
1384 |
Node max; |
* on a SubMap. |
1385 |
|
*/ |
1386 |
/* Create Iterator with the supplied type: KEYS, VALUES, or ENTRIES */ |
private final Node max; |
1387 |
|
|
1388 |
|
/** |
1389 |
|
* Construct a new TreeIterator with the supplied type. |
1390 |
|
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES} |
1391 |
|
*/ |
1392 |
TreeIterator(int type) |
TreeIterator(int type) |
1393 |
{ |
{ |
1394 |
this.type = type; |
this(type, firstNode(), nil); |
|
this.next = firstNode(); |
|
1395 |
} |
} |
1396 |
|
|
1397 |
/* Construct an interator for a SubMap. Iteration will begin at node |
/** |
1398 |
"first", and stop when "max" is reached. */ |
* Construct a new TreeIterator with the supplied type. Iteration will |
1399 |
|
* be from "first" (inclusive) to "max" (exclusive). |
1400 |
|
* |
1401 |
|
* @param type {@link #KEYS}, {@link #VALUES}, or {@link #ENTRIES} |
1402 |
|
* @param first where to start iteration, nil for empty iterator |
1403 |
|
* @param max the cutoff for iteration, nil for all remaining nodes |
1404 |
|
*/ |
1405 |
TreeIterator(int type, Node first, Node max) |
TreeIterator(int type, Node first, Node max) |
1406 |
{ |
{ |
1407 |
this.type = type; |
this.type = type; |
1409 |
this.max = max; |
this.max = max; |
1410 |
} |
} |
1411 |
|
|
1412 |
|
/** |
1413 |
|
* Returns true if the Iterator has more elements. |
1414 |
|
* @return true if there are more elements |
1415 |
|
* @throws ConcurrentModificationException if the TreeMap was modified |
1416 |
|
*/ |
1417 |
public boolean hasNext() |
public boolean hasNext() |
1418 |
{ |
{ |
1419 |
if (knownMod != TreeMap.this.modCount) |
if (knownMod != modCount) |
1420 |
throw new ConcurrentModificationException(); |
throw new ConcurrentModificationException(); |
1421 |
return (next != nil); |
return next != max; |
1422 |
} |
} |
1423 |
|
|
1424 |
|
/** |
1425 |
|
* Returns the next element in the Iterator's sequential view. |
1426 |
|
* @return the next element |
1427 |
|
* @throws ConcurrentModificationException if the TreeMap was modified |
1428 |
|
* @throws NoSuchElementException if there is none |
1429 |
|
*/ |
1430 |
public Object next() |
public Object next() |
1431 |
{ |
{ |
1432 |
if (next == nil) |
if (knownMod != modCount) |
1433 |
throw new NoSuchElementException(); |
throw new ConcurrentModificationException(); |
1434 |
if (knownMod != TreeMap.this.modCount) |
if (next == max) |
1435 |
throw new ConcurrentModificationException(); |
throw new NoSuchElementException(); |
1436 |
Node n = next; |
last = next; |
1437 |
|
next = successor(last); |
1438 |
// Check limit in case we are iterating through a submap. |
|
|
if (n != max) |
|
|
next = successor(n); |
|
|
else |
|
|
next = nil; |
|
|
|
|
|
last = n; |
|
|
|
|
1439 |
if (type == VALUES) |
if (type == VALUES) |
1440 |
return n.value; |
return last.value; |
1441 |
else if (type == KEYS) |
else if (type == KEYS) |
1442 |
return n.key; |
return last.key; |
1443 |
return n; |
return last; |
1444 |
} |
} |
1445 |
|
|
1446 |
|
/** |
1447 |
|
* Removes from the backing TreeMap the last element which was fetched |
1448 |
|
* with the <code>next()</code> method. |
1449 |
|
* @throws ConcurrentModificationException if the TreeMap was modified |
1450 |
|
* @throws IllegalStateException if called when there is no last element |
1451 |
|
*/ |
1452 |
public void remove() |
public void remove() |
1453 |
{ |
{ |
1454 |
|
if (knownMod != modCount) |
1455 |
|
throw new ConcurrentModificationException(); |
1456 |
if (last == null) |
if (last == null) |
1457 |
throw new IllegalStateException(); |
throw new IllegalStateException(); |
1458 |
if (knownMod != TreeMap.this.modCount) |
|
1459 |
throw new ConcurrentModificationException(); |
removeNode(last); |
|
/* |
|
|
Object key = null; |
|
|
if (next != nil) |
|
|
key = next.key; |
|
|
*/ |
|
|
TreeMap.this.removeNode(last); |
|
|
knownMod++; |
|
|
/* |
|
|
if (key != null) |
|
|
next = getNode(key); |
|
|
*/ |
|
1460 |
last = null; |
last = null; |
1461 |
|
knownMod++; |
1462 |
} |
} |
1463 |
} |
} // class TreeIterator |
1464 |
|
|
1465 |
class SubMap extends AbstractMap implements SortedMap |
/** |
1466 |
|
* Implementation of {@link #subMap(Object, Object)} and other map |
1467 |
|
* ranges. This class provides a view of a portion of the original backing |
1468 |
|
* map, and throws {@link IllegalArgumentException} for attempts to |
1469 |
|
* access beyond that range. |
1470 |
|
* |
1471 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
1472 |
|
*/ |
1473 |
|
private final class SubMap extends AbstractMap implements SortedMap |
1474 |
{ |
{ |
1475 |
Object minKey; |
/** |
1476 |
Object maxKey; |
* The lower range of this view, inclusive, or nil for unbounded. |
1477 |
|
* Package visible for use by nested classes. |
1478 |
/* Create a SubMap representing the elements between minKey and maxKey |
*/ |
1479 |
(inclusive). If minKey is nil, SubMap has no lower bound (headMap). |
final Object minKey; |
1480 |
If maxKey is nil, the SubMap has no upper bound (tailMap). */ |
|
1481 |
|
/** |
1482 |
|
* The upper range of this view, exclusive, or nil for unbounded. |
1483 |
|
* Package visible for use by nested classes. |
1484 |
|
*/ |
1485 |
|
final Object maxKey; |
1486 |
|
|
1487 |
|
/** |
1488 |
|
* The cache for {@link #entrySet()}. |
1489 |
|
*/ |
1490 |
|
private Set entries; |
1491 |
|
|
1492 |
|
/** |
1493 |
|
* Create a SubMap representing the elements between minKey (inclusive) |
1494 |
|
* and maxKey (exclusive). If minKey is nil, SubMap has no lower bound |
1495 |
|
* (headMap). If maxKey is nil, the SubMap has no upper bound (tailMap). |
1496 |
|
* |
1497 |
|
* @param minKey the lower bound |
1498 |
|
* @param maxKey the upper bound |
1499 |
|
* @throws IllegalArgumentException if minKey > maxKey |
1500 |
|
*/ |
1501 |
SubMap(Object minKey, Object maxKey) |
SubMap(Object minKey, Object maxKey) |
1502 |
{ |
{ |
1503 |
|
if (minKey != nil && maxKey != nil && compare(minKey, maxKey) > 0) |
1504 |
|
throw new IllegalArgumentException("fromKey > toKey"); |
1505 |
this.minKey = minKey; |
this.minKey = minKey; |
1506 |
this.maxKey = maxKey; |
this.maxKey = maxKey; |
1507 |
} |
} |
1508 |
|
|
1509 |
|
/** |
1510 |
|
* Check if "key" is in within the range bounds for this SubMap. The |
1511 |
|
* lower ("from") SubMap range is inclusive, and the upper ("to") bound |
1512 |
|
* is exclusive. Package visible for use by nested classes. |
1513 |
|
* |
1514 |
|
* @param key the key to check |
1515 |
|
* @return true if the key is in range |
1516 |
|
*/ |
1517 |
|
final boolean keyInRange(Object key) |
1518 |
|
{ |
1519 |
|
return ((minKey == nil || compare(key, minKey) >= 0) |
1520 |
|
&& (maxKey == nil || compare(key, maxKey) < 0)); |
1521 |
|
} |
1522 |
|
|
1523 |
public void clear() |
public void clear() |
1524 |
{ |
{ |
1525 |
Node current; |
Node next = lowestGreaterThan(minKey, true); |
1526 |
Node next = lowestGreaterThan(minKey); |
Node max = lowestGreaterThan(maxKey, false); |
1527 |
Node max = highestLessThan(maxKey); |
while (next != max) |
|
|
|
|
if (compare(next.key, max.key) > 0) |
|
|
// Nothing to delete. |
|
|
return; |
|
|
|
|
|
do |
|
1528 |
{ |
{ |
1529 |
current = next; |
Node current = next; |
1530 |
next = successor(current); |
next = successor(current); |
1531 |
remove(current); |
removeNode(current); |
1532 |
} |
} |
1533 |
while (current != max); |
} |
1534 |
} |
|
1535 |
|
public Comparator comparator() |
|
/* Check if "key" is in within the range bounds for this SubMap. |
|
|
The lower ("from") SubMap range is inclusive, and the upper (to) bound |
|
|
is exclusive. */ |
|
|
private boolean keyInRange(Object key) |
|
1536 |
{ |
{ |
1537 |
return ((minKey == nil || compare(key, minKey) >= 0) |
return comparator; |
|
&& (maxKey == nil || compare(key, maxKey) < 0)); |
|
1538 |
} |
} |
1539 |
|
|
1540 |
public boolean containsKey(Object key) |
public boolean containsKey(Object key) |
1541 |
{ |
{ |
1542 |
return (keyInRange(key) && TreeMap.this.containsKey(key)); |
return keyInRange(key) && TreeMap.this.containsKey(key); |
1543 |
} |
} |
1544 |
|
|
1545 |
public boolean containsValue(Object value) |
public boolean containsValue(Object value) |
1546 |
{ |
{ |
1547 |
Node node = lowestGreaterThan(minKey); |
Node node = lowestGreaterThan(minKey, true); |
1548 |
Node max = highestLessThan(maxKey); |
Node max = lowestGreaterThan(maxKey, false); |
1549 |
Object currentVal; |
while (node != max) |
1550 |
|
{ |
1551 |
if (node == nil || max == nil || compare(node.key, max.key) > 0) |
if (equals(value, node.getValue())) |
1552 |
// Nothing to search. |
return true; |
1553 |
return false; |
node = successor(node); |
1554 |
|
} |
1555 |
while (true) |
return false; |
|
{ |
|
|
currentVal = node.getValue(); |
|
|
if (value == null ? currentVal == null : value.equals (currentVal)) |
|
|
return true; |
|
|
if (node == max) |
|
|
return false; |
|
|
node = successor(node); |
|
|
} |
|
1556 |
} |
} |
1557 |
|
|
1558 |
public Object get(Object key) |
public Set entrySet() |
1559 |
{ |
{ |
1560 |
if (keyInRange(key)) |
if (entries == null) |
1561 |
return TreeMap.this.get(key); |
// Create an AbstractSet with custom implementations of those methods |
1562 |
return null; |
// that can be overriden easily and efficiently. |
1563 |
|
entries = new AbstractSet() |
1564 |
|
{ |
1565 |
|
public int size() |
1566 |
|
{ |
1567 |
|
return SubMap.this.size(); |
1568 |
|
} |
1569 |
|
|
1570 |
|
public Iterator iterator() |
1571 |
|
{ |
1572 |
|
Node first = lowestGreaterThan(minKey, true); |
1573 |
|
Node max = lowestGreaterThan(maxKey, false); |
1574 |
|
return new TreeIterator(ENTRIES, first, max); |
1575 |
|
} |
1576 |
|
|
1577 |
|
public void clear() |
1578 |
|
{ |
1579 |
|
SubMap.this.clear(); |
1580 |
|
} |
1581 |
|
|
1582 |
|
public boolean contains(Object o) |
1583 |
|
{ |
1584 |
|
if (! (o instanceof Map.Entry)) |
1585 |
|
return false; |
1586 |
|
Map.Entry me = (Map.Entry) o; |
1587 |
|
Object key = me.getKey(); |
1588 |
|
if (! keyInRange(key)) |
1589 |
|
return false; |
1590 |
|
Node n = getNode(key); |
1591 |
|
return n != nil && AbstractSet.equals(me.getValue(), n.value); |
1592 |
|
} |
1593 |
|
|
1594 |
|
public boolean remove(Object o) |
1595 |
|
{ |
1596 |
|
if (! (o instanceof Map.Entry)) |
1597 |
|
return false; |
1598 |
|
Map.Entry me = (Map.Entry) o; |
1599 |
|
Object key = me.getKey(); |
1600 |
|
if (! keyInRange(key)) |
1601 |
|
return false; |
1602 |
|
Node n = getNode(key); |
1603 |
|
if (n != nil && AbstractSet.equals(me.getValue(), n.value)) |
1604 |
|
{ |
1605 |
|
removeNode(n); |
1606 |
|
return true; |
1607 |
|
} |
1608 |
|
return false; |
1609 |
|
} |
1610 |
|
}; |
1611 |
|
return entries; |
1612 |
} |
} |
1613 |
|
|
1614 |
public Object put(Object key, Object value) |
public Object firstKey() |
1615 |
{ |
{ |
1616 |
if (keyInRange(key)) |
Node node = lowestGreaterThan(minKey, true); |
1617 |
return TreeMap.this.put(key, value); |
if (node == nil || ! keyInRange(node.key)) |
1618 |
else |
throw new NoSuchElementException(); |
1619 |
throw new IllegalArgumentException("Key outside range"); |
return node.key; |
1620 |
} |
} |
1621 |
|
|
1622 |
public Object remove(Object key) |
public Object get(Object key) |
1623 |
{ |
{ |
1624 |
if (keyInRange(key)) |
if (keyInRange(key)) |
1625 |
return TreeMap.this.remove(key); |
return TreeMap.this.get(key); |
1626 |
else |
return null; |
|
return null; |
|
1627 |
} |
} |
1628 |
|
|
1629 |
public int size() |
public SortedMap headMap(Object toKey) |
1630 |
{ |
{ |
1631 |
Node node = lowestGreaterThan(minKey); |
if (! keyInRange(toKey)) |
1632 |
Node max = highestLessThan(maxKey); |
throw new IllegalArgumentException("key outside range"); |
1633 |
|
return new SubMap(minKey, toKey); |
1634 |
if (node == nil || max == nil || compare(node.key, max.key) > 0) |
} |
|
return 0; // Empty. |
|
1635 |
|
|
1636 |
int count = 1; |
public Set keySet() |
1637 |
while (node != max) |
{ |
1638 |
|
if (this.keys == null) |
1639 |
|
// Create an AbstractSet with custom implementations of those methods |
1640 |
|
// that can be overriden easily and efficiently. |
1641 |
|
this.keys = new AbstractSet() |
1642 |
{ |
{ |
1643 |
count++; |
public int size() |
1644 |
node = successor(node); |
{ |
1645 |
} |
return SubMap.this.size(); |
1646 |
|
} |
1647 |
|
|
1648 |
return count; |
public Iterator iterator() |
1649 |
|
{ |
1650 |
|
Node first = lowestGreaterThan(minKey, true); |
1651 |
|
Node max = lowestGreaterThan(maxKey, false); |
1652 |
|
return new TreeIterator(KEYS, first, max); |
1653 |
|
} |
1654 |
|
|
1655 |
|
public void clear() |
1656 |
|
{ |
1657 |
|
SubMap.this.clear(); |
1658 |
|
} |
1659 |
|
|
1660 |
|
public boolean contains(Object o) |
1661 |
|
{ |
1662 |
|
if (! keyInRange(o)) |
1663 |
|
return false; |
1664 |
|
return getNode(o) != nil; |
1665 |
|
} |
1666 |
|
|
1667 |
|
public boolean remove(Object o) |
1668 |
|
{ |
1669 |
|
if (! keyInRange(o)) |
1670 |
|
return false; |
1671 |
|
Node n = getNode(o); |
1672 |
|
if (n != nil) |
1673 |
|
{ |
1674 |
|
removeNode(n); |
1675 |
|
return true; |
1676 |
|
} |
1677 |
|
return false; |
1678 |
|
} |
1679 |
|
}; |
1680 |
|
return this.keys; |
1681 |
} |
} |
1682 |
|
|
1683 |
public Set entrySet() |
public Object lastKey() |
1684 |
{ |
{ |
1685 |
// Create an AbstractSet with custom implementations of those methods that |
Node node = highestLessThan(maxKey); |
1686 |
// can be overriden easily and efficiently. |
if (node == nil || ! keyInRange(node.key)) |
1687 |
return new AbstractSet() |
throw new NoSuchElementException(); |
1688 |
{ |
return node.key; |
|
public int size() |
|
|
{ |
|
|
return SubMap.this.size(); |
|
|
} |
|
|
|
|
|
public Iterator iterator() |
|
|
{ |
|
|
Node first = lowestGreaterThan(minKey); |
|
|
Node max = highestLessThan(maxKey); |
|
|
return new TreeIterator(TreeIterator.ENTRIES, first, max); |
|
|
} |
|
|
|
|
|
public void clear() |
|
|
{ |
|
|
this.clear(); |
|
|
} |
|
|
|
|
|
public boolean contains(Object o) |
|
|
{ |
|
|
if (!(o instanceof Map.Entry)) |
|
|
return false; |
|
|
Map.Entry me = (Map.Entry) o; |
|
|
Object key = me.getKey(); |
|
|
if (!keyInRange(key)) |
|
|
return false; |
|
|
Node n = getNode(key); |
|
|
return (n != nil && me.getValue().equals(n.value)); |
|
|
} |
|
|
|
|
|
public boolean remove(Object o) |
|
|
{ |
|
|
if (!(o instanceof Map.Entry)) |
|
|
return false; |
|
|
Map.Entry me = (Map.Entry) o; |
|
|
Object key = me.getKey(); |
|
|
if (!keyInRange(key)) |
|
|
return false; |
|
|
Node n = getNode(key); |
|
|
if (n != nil && me.getValue().equals(n.value)) |
|
|
{ |
|
|
removeNode(n); |
|
|
return true; |
|
|
} |
|
|
return false; |
|
|
} |
|
|
}; |
|
1689 |
} |
} |
1690 |
|
|
1691 |
public Comparator comparator() |
public Object put(Object key, Object value) |
1692 |
{ |
{ |
1693 |
return comparator; |
if (! keyInRange(key)) |
1694 |
|
throw new IllegalArgumentException("Key outside range"); |
1695 |
|
return TreeMap.this.put(key, value); |
1696 |
} |
} |
1697 |
|
|
1698 |
public Object firstKey() |
public Object remove(Object key) |
1699 |
{ |
{ |
1700 |
Node node = lowestGreaterThan(minKey); |
if (keyInRange(key)) |
1701 |
if (node == nil || !keyInRange(node.key)) |
return TreeMap.this.remove(key); |
1702 |
throw new NoSuchElementException ("empty"); |
return null; |
|
return node.key; |
|
1703 |
} |
} |
1704 |
|
|
1705 |
public Object lastKey() |
public int size() |
1706 |
{ |
{ |
1707 |
Node node = highestLessThan(maxKey); |
Node node = lowestGreaterThan(minKey, true); |
1708 |
if (node == nil || !keyInRange(node.key)) |
Node max = lowestGreaterThan(maxKey, false); |
1709 |
throw new NoSuchElementException ("empty"); |
int count = 0; |
1710 |
return node.key; |
while (node != max) |
1711 |
|
{ |
1712 |
|
count++; |
1713 |
|
node = successor(node); |
1714 |
|
} |
1715 |
|
return count; |
1716 |
} |
} |
1717 |
|
|
1718 |
public SortedMap subMap(Object fromKey, Object toKey) |
public SortedMap subMap(Object fromKey, Object toKey) |
1719 |
{ |
{ |
1720 |
if (!keyInRange(fromKey) || !keyInRange(toKey)) |
if (! keyInRange(fromKey) || ! keyInRange(toKey)) |
1721 |
throw new IllegalArgumentException("key outside range"); |
throw new IllegalArgumentException("key outside range"); |
1722 |
|
return new SubMap(fromKey, toKey); |
|
return TreeMap.this.subMap(fromKey, toKey); |
|
1723 |
} |
} |
1724 |
|
|
1725 |
public SortedMap headMap(Object toKey) |
public SortedMap tailMap(Object fromKey) |
1726 |
{ |
{ |
1727 |
if (!keyInRange(toKey)) |
if (! keyInRange(fromKey)) |
1728 |
throw new IllegalArgumentException("key outside range"); |
throw new IllegalArgumentException("key outside range"); |
1729 |
|
return new SubMap(fromKey, maxKey); |
|
return TreeMap.this.subMap(minKey, toKey); |
|
1730 |
} |
} |
1731 |
|
|
1732 |
public SortedMap tailMap(Object fromKey) |
public Collection values() |
1733 |
{ |
{ |
1734 |
if (!keyInRange(fromKey)) |
if (this.values == null) |
1735 |
throw new IllegalArgumentException("key outside range"); |
// Create an AbstractCollection with custom implementations of those |
1736 |
|
// methods that can be overriden easily and efficiently. |
1737 |
|
this.values = new AbstractCollection() |
1738 |
|
{ |
1739 |
|
public int size() |
1740 |
|
{ |
1741 |
|
return SubMap.this.size(); |
1742 |
|
} |
1743 |
|
|
1744 |
return TreeMap.this.subMap(fromKey, maxKey); |
public Iterator iterator() |
1745 |
|
{ |
1746 |
|
Node first = lowestGreaterThan(minKey, true); |
1747 |
|
Node max = lowestGreaterThan(maxKey, false); |
1748 |
|
return new TreeIterator(VALUES, first, max); |
1749 |
|
} |
1750 |
|
|
1751 |
|
public void clear() |
1752 |
|
{ |
1753 |
|
SubMap.this.clear(); |
1754 |
|
} |
1755 |
|
}; |
1756 |
|
return this.keys; |
1757 |
} |
} |
1758 |
} |
} // class SubMap |
1759 |
} |
} // class TreeMap |