rlm@10
|
1 /**
|
rlm@10
|
2 * Copyright (c) Rich Hickey. All rights reserved.
|
rlm@10
|
3 * The use and distribution terms for this software are covered by the
|
rlm@10
|
4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
|
rlm@10
|
5 * which can be found in the file epl-v10.html at the root of this distribution.
|
rlm@10
|
6 * By using this software in any fashion, you are agreeing to be bound by
|
rlm@10
|
7 * the terms of this license.
|
rlm@10
|
8 * You must not remove this notice, or any other, from this software.
|
rlm@10
|
9 **/
|
rlm@10
|
10
|
rlm@10
|
11 /* rich May 20, 2006 */
|
rlm@10
|
12
|
rlm@10
|
13 package clojure.lang;
|
rlm@10
|
14
|
rlm@10
|
15 import java.util.*;
|
rlm@10
|
16
|
rlm@10
|
17 /**
|
rlm@10
|
18 * Persistent Red Black Tree
|
rlm@10
|
19 * Note that instances of this class are constant values
|
rlm@10
|
20 * i.e. add/remove etc return new values
|
rlm@10
|
21 * <p/>
|
rlm@10
|
22 * See Okasaki, Kahrs, Larsen et al
|
rlm@10
|
23 */
|
rlm@10
|
24
|
rlm@10
|
25 public class PersistentTreeMap extends APersistentMap implements IObj, Reversible, Sorted{
|
rlm@10
|
26
|
rlm@10
|
27 public final Comparator comp;
|
rlm@10
|
28 public final Node tree;
|
rlm@10
|
29 public final int _count;
|
rlm@10
|
30 final IPersistentMap _meta;
|
rlm@10
|
31
|
rlm@10
|
32 final static public PersistentTreeMap EMPTY = new PersistentTreeMap();
|
rlm@10
|
33
|
rlm@10
|
34 static public IPersistentMap create(Map other){
|
rlm@10
|
35 IPersistentMap ret = EMPTY;
|
rlm@10
|
36 for(Object o : other.entrySet())
|
rlm@10
|
37 {
|
rlm@10
|
38 Map.Entry e = (Entry) o;
|
rlm@10
|
39 ret = ret.assoc(e.getKey(), e.getValue());
|
rlm@10
|
40 }
|
rlm@10
|
41 return ret;
|
rlm@10
|
42 }
|
rlm@10
|
43
|
rlm@10
|
44 public PersistentTreeMap(){
|
rlm@10
|
45 this(RT.DEFAULT_COMPARATOR);
|
rlm@10
|
46 }
|
rlm@10
|
47
|
rlm@10
|
48 public PersistentTreeMap withMeta(IPersistentMap meta){
|
rlm@10
|
49 return new PersistentTreeMap(meta, comp, tree, _count);
|
rlm@10
|
50 }
|
rlm@10
|
51
|
rlm@10
|
52 private PersistentTreeMap(Comparator comp){
|
rlm@10
|
53 this(null, comp);
|
rlm@10
|
54 }
|
rlm@10
|
55
|
rlm@10
|
56
|
rlm@10
|
57 public PersistentTreeMap(IPersistentMap meta, Comparator comp){
|
rlm@10
|
58 this.comp = comp;
|
rlm@10
|
59 this._meta = meta;
|
rlm@10
|
60 tree = null;
|
rlm@10
|
61 _count = 0;
|
rlm@10
|
62 }
|
rlm@10
|
63
|
rlm@10
|
64 PersistentTreeMap(IPersistentMap meta, Comparator comp, Node tree, int _count){
|
rlm@10
|
65 this._meta = meta;
|
rlm@10
|
66 this.comp = comp;
|
rlm@10
|
67 this.tree = tree;
|
rlm@10
|
68 this._count = _count;
|
rlm@10
|
69 }
|
rlm@10
|
70
|
rlm@10
|
71 static public PersistentTreeMap create(ISeq items){
|
rlm@10
|
72 IPersistentMap ret = EMPTY;
|
rlm@10
|
73 for(; items != null; items = items.next().next())
|
rlm@10
|
74 {
|
rlm@10
|
75 if(items.next() == null)
|
rlm@10
|
76 throw new IllegalArgumentException(String.format("No value supplied for key: %s", items.first()));
|
rlm@10
|
77 ret = ret.assoc(items.first(), RT.second(items));
|
rlm@10
|
78 }
|
rlm@10
|
79 return (PersistentTreeMap) ret;
|
rlm@10
|
80 }
|
rlm@10
|
81
|
rlm@10
|
82 static public PersistentTreeMap create(Comparator comp, ISeq items){
|
rlm@10
|
83 IPersistentMap ret = new PersistentTreeMap(comp);
|
rlm@10
|
84 for(; items != null; items = items.next().next())
|
rlm@10
|
85 {
|
rlm@10
|
86 if(items.next() == null)
|
rlm@10
|
87 throw new IllegalArgumentException(String.format("No value supplied for key: %s", items.first()));
|
rlm@10
|
88 ret = ret.assoc(items.first(), RT.second(items));
|
rlm@10
|
89 }
|
rlm@10
|
90 return (PersistentTreeMap) ret;
|
rlm@10
|
91 }
|
rlm@10
|
92
|
rlm@10
|
93 public boolean containsKey(Object key){
|
rlm@10
|
94 return entryAt(key) != null;
|
rlm@10
|
95 }
|
rlm@10
|
96
|
rlm@10
|
97 public PersistentTreeMap assocEx(Object key, Object val) throws Exception{
|
rlm@10
|
98 Box found = new Box(null);
|
rlm@10
|
99 Node t = add(tree, key, val, found);
|
rlm@10
|
100 if(t == null) //null == already contains key
|
rlm@10
|
101 {
|
rlm@10
|
102 throw new Exception("Key already present");
|
rlm@10
|
103 }
|
rlm@10
|
104 return new PersistentTreeMap(comp, t.blacken(), _count + 1, meta());
|
rlm@10
|
105 }
|
rlm@10
|
106
|
rlm@10
|
107 public PersistentTreeMap assoc(Object key, Object val){
|
rlm@10
|
108 Box found = new Box(null);
|
rlm@10
|
109 Node t = add(tree, key, val, found);
|
rlm@10
|
110 if(t == null) //null == already contains key
|
rlm@10
|
111 {
|
rlm@10
|
112 Node foundNode = (Node) found.val;
|
rlm@10
|
113 if(foundNode.val() == val) //note only get same collection on identity of val, not equals()
|
rlm@10
|
114 return this;
|
rlm@10
|
115 return new PersistentTreeMap(comp, replace(tree, key, val), _count, meta());
|
rlm@10
|
116 }
|
rlm@10
|
117 return new PersistentTreeMap(comp, t.blacken(), _count + 1, meta());
|
rlm@10
|
118 }
|
rlm@10
|
119
|
rlm@10
|
120
|
rlm@10
|
121 public PersistentTreeMap without(Object key){
|
rlm@10
|
122 Box found = new Box(null);
|
rlm@10
|
123 Node t = remove(tree, key, found);
|
rlm@10
|
124 if(t == null)
|
rlm@10
|
125 {
|
rlm@10
|
126 if(found.val == null)//null == doesn't contain key
|
rlm@10
|
127 return this;
|
rlm@10
|
128 //empty
|
rlm@10
|
129 return new PersistentTreeMap(meta(), comp);
|
rlm@10
|
130 }
|
rlm@10
|
131 return new PersistentTreeMap(comp, t.blacken(), _count - 1, meta());
|
rlm@10
|
132 }
|
rlm@10
|
133
|
rlm@10
|
134 public ISeq seq(){
|
rlm@10
|
135 if(_count > 0)
|
rlm@10
|
136 return Seq.create(tree, true, _count);
|
rlm@10
|
137 return null;
|
rlm@10
|
138 }
|
rlm@10
|
139
|
rlm@10
|
140 public IPersistentCollection empty(){
|
rlm@10
|
141 return new PersistentTreeMap(meta(), comp);
|
rlm@10
|
142 }
|
rlm@10
|
143
|
rlm@10
|
144 public ISeq rseq() throws Exception{
|
rlm@10
|
145 if(_count > 0)
|
rlm@10
|
146 return Seq.create(tree, false, _count);
|
rlm@10
|
147 return null;
|
rlm@10
|
148 }
|
rlm@10
|
149
|
rlm@10
|
150 public Comparator comparator(){
|
rlm@10
|
151 return comp;
|
rlm@10
|
152 }
|
rlm@10
|
153
|
rlm@10
|
154 public Object entryKey(Object entry){
|
rlm@10
|
155 return ((IMapEntry) entry).key();
|
rlm@10
|
156 }
|
rlm@10
|
157
|
rlm@10
|
158 public ISeq seq(boolean ascending){
|
rlm@10
|
159 if(_count > 0)
|
rlm@10
|
160 return Seq.create(tree, ascending, _count);
|
rlm@10
|
161 return null;
|
rlm@10
|
162 }
|
rlm@10
|
163
|
rlm@10
|
164 public ISeq seqFrom(Object key, boolean ascending){
|
rlm@10
|
165 if(_count > 0)
|
rlm@10
|
166 {
|
rlm@10
|
167 ISeq stack = null;
|
rlm@10
|
168 Node t = tree;
|
rlm@10
|
169 while(t != null)
|
rlm@10
|
170 {
|
rlm@10
|
171 int c = doCompare(key, t.key);
|
rlm@10
|
172 if(c == 0)
|
rlm@10
|
173 {
|
rlm@10
|
174 stack = RT.cons(t, stack);
|
rlm@10
|
175 return new Seq(stack, ascending);
|
rlm@10
|
176 }
|
rlm@10
|
177 else if(ascending)
|
rlm@10
|
178 {
|
rlm@10
|
179 if(c < 0)
|
rlm@10
|
180 {
|
rlm@10
|
181 stack = RT.cons(t, stack);
|
rlm@10
|
182 t = t.left();
|
rlm@10
|
183 }
|
rlm@10
|
184 else
|
rlm@10
|
185 t = t.right();
|
rlm@10
|
186 }
|
rlm@10
|
187 else
|
rlm@10
|
188 {
|
rlm@10
|
189 if(c > 0)
|
rlm@10
|
190 {
|
rlm@10
|
191 stack = RT.cons(t, stack);
|
rlm@10
|
192 t = t.right();
|
rlm@10
|
193 }
|
rlm@10
|
194 else
|
rlm@10
|
195 t = t.left();
|
rlm@10
|
196 }
|
rlm@10
|
197 }
|
rlm@10
|
198 if(stack != null)
|
rlm@10
|
199 return new Seq(stack, ascending);
|
rlm@10
|
200 }
|
rlm@10
|
201 return null;
|
rlm@10
|
202 }
|
rlm@10
|
203
|
rlm@10
|
204 public NodeIterator iterator(){
|
rlm@10
|
205 return new NodeIterator(tree, true);
|
rlm@10
|
206 }
|
rlm@10
|
207
|
rlm@10
|
208 public NodeIterator reverseIterator(){
|
rlm@10
|
209 return new NodeIterator(tree, false);
|
rlm@10
|
210 }
|
rlm@10
|
211
|
rlm@10
|
212 public Iterator keys(){
|
rlm@10
|
213 return keys(iterator());
|
rlm@10
|
214 }
|
rlm@10
|
215
|
rlm@10
|
216 public Iterator vals(){
|
rlm@10
|
217 return vals(iterator());
|
rlm@10
|
218 }
|
rlm@10
|
219
|
rlm@10
|
220 public Iterator keys(NodeIterator it){
|
rlm@10
|
221 return new KeyIterator(it);
|
rlm@10
|
222 }
|
rlm@10
|
223
|
rlm@10
|
224 public Iterator vals(NodeIterator it){
|
rlm@10
|
225 return new ValIterator(it);
|
rlm@10
|
226 }
|
rlm@10
|
227
|
rlm@10
|
228 public Object minKey(){
|
rlm@10
|
229 Node t = min();
|
rlm@10
|
230 return t != null ? t.key : null;
|
rlm@10
|
231 }
|
rlm@10
|
232
|
rlm@10
|
233 public Node min(){
|
rlm@10
|
234 Node t = tree;
|
rlm@10
|
235 if(t != null)
|
rlm@10
|
236 {
|
rlm@10
|
237 while(t.left() != null)
|
rlm@10
|
238 t = t.left();
|
rlm@10
|
239 }
|
rlm@10
|
240 return t;
|
rlm@10
|
241 }
|
rlm@10
|
242
|
rlm@10
|
243 public Object maxKey(){
|
rlm@10
|
244 Node t = max();
|
rlm@10
|
245 return t != null ? t.key : null;
|
rlm@10
|
246 }
|
rlm@10
|
247
|
rlm@10
|
248 public Node max(){
|
rlm@10
|
249 Node t = tree;
|
rlm@10
|
250 if(t != null)
|
rlm@10
|
251 {
|
rlm@10
|
252 while(t.right() != null)
|
rlm@10
|
253 t = t.right();
|
rlm@10
|
254 }
|
rlm@10
|
255 return t;
|
rlm@10
|
256 }
|
rlm@10
|
257
|
rlm@10
|
258 public int depth(){
|
rlm@10
|
259 return depth(tree);
|
rlm@10
|
260 }
|
rlm@10
|
261
|
rlm@10
|
262 int depth(Node t){
|
rlm@10
|
263 if(t == null)
|
rlm@10
|
264 return 0;
|
rlm@10
|
265 return 1 + Math.max(depth(t.left()), depth(t.right()));
|
rlm@10
|
266 }
|
rlm@10
|
267
|
rlm@10
|
268 public Object valAt(Object key, Object notFound){
|
rlm@10
|
269 Node n = entryAt(key);
|
rlm@10
|
270 return (n != null) ? n.val() : notFound;
|
rlm@10
|
271 }
|
rlm@10
|
272
|
rlm@10
|
273 public Object valAt(Object key){
|
rlm@10
|
274 return valAt(key, null);
|
rlm@10
|
275 }
|
rlm@10
|
276
|
rlm@10
|
277 public int capacity(){
|
rlm@10
|
278 return _count;
|
rlm@10
|
279 }
|
rlm@10
|
280
|
rlm@10
|
281 public int count(){
|
rlm@10
|
282 return _count;
|
rlm@10
|
283 }
|
rlm@10
|
284
|
rlm@10
|
285 public Node entryAt(Object key){
|
rlm@10
|
286 Node t = tree;
|
rlm@10
|
287 while(t != null)
|
rlm@10
|
288 {
|
rlm@10
|
289 int c = doCompare(key, t.key);
|
rlm@10
|
290 if(c == 0)
|
rlm@10
|
291 return t;
|
rlm@10
|
292 else if(c < 0)
|
rlm@10
|
293 t = t.left();
|
rlm@10
|
294 else
|
rlm@10
|
295 t = t.right();
|
rlm@10
|
296 }
|
rlm@10
|
297 return t;
|
rlm@10
|
298 }
|
rlm@10
|
299
|
rlm@10
|
300 public int doCompare(Object k1, Object k2){
|
rlm@10
|
301 // if(comp != null)
|
rlm@10
|
302 return comp.compare(k1, k2);
|
rlm@10
|
303 // return ((Comparable) k1).compareTo(k2);
|
rlm@10
|
304 }
|
rlm@10
|
305
|
rlm@10
|
306 Node add(Node t, Object key, Object val, Box found){
|
rlm@10
|
307 if(t == null)
|
rlm@10
|
308 {
|
rlm@10
|
309 if(val == null)
|
rlm@10
|
310 return new Red(key);
|
rlm@10
|
311 return new RedVal(key, val);
|
rlm@10
|
312 }
|
rlm@10
|
313 int c = doCompare(key, t.key);
|
rlm@10
|
314 if(c == 0)
|
rlm@10
|
315 {
|
rlm@10
|
316 found.val = t;
|
rlm@10
|
317 return null;
|
rlm@10
|
318 }
|
rlm@10
|
319 Node ins = c < 0 ? add(t.left(), key, val, found) : add(t.right(), key, val, found);
|
rlm@10
|
320 if(ins == null) //found below
|
rlm@10
|
321 return null;
|
rlm@10
|
322 if(c < 0)
|
rlm@10
|
323 return t.addLeft(ins);
|
rlm@10
|
324 return t.addRight(ins);
|
rlm@10
|
325 }
|
rlm@10
|
326
|
rlm@10
|
327 Node remove(Node t, Object key, Box found){
|
rlm@10
|
328 if(t == null)
|
rlm@10
|
329 return null; //not found indicator
|
rlm@10
|
330 int c = doCompare(key, t.key);
|
rlm@10
|
331 if(c == 0)
|
rlm@10
|
332 {
|
rlm@10
|
333 found.val = t;
|
rlm@10
|
334 return append(t.left(), t.right());
|
rlm@10
|
335 }
|
rlm@10
|
336 Node del = c < 0 ? remove(t.left(), key, found) : remove(t.right(), key, found);
|
rlm@10
|
337 if(del == null && found.val == null) //not found below
|
rlm@10
|
338 return null;
|
rlm@10
|
339 if(c < 0)
|
rlm@10
|
340 {
|
rlm@10
|
341 if(t.left() instanceof Black)
|
rlm@10
|
342 return balanceLeftDel(t.key, t.val(), del, t.right());
|
rlm@10
|
343 else
|
rlm@10
|
344 return red(t.key, t.val(), del, t.right());
|
rlm@10
|
345 }
|
rlm@10
|
346 if(t.right() instanceof Black)
|
rlm@10
|
347 return balanceRightDel(t.key, t.val(), t.left(), del);
|
rlm@10
|
348 return red(t.key, t.val(), t.left(), del);
|
rlm@10
|
349 // return t.removeLeft(del);
|
rlm@10
|
350 // return t.removeRight(del);
|
rlm@10
|
351 }
|
rlm@10
|
352
|
rlm@10
|
353 static Node append(Node left, Node right){
|
rlm@10
|
354 if(left == null)
|
rlm@10
|
355 return right;
|
rlm@10
|
356 else if(right == null)
|
rlm@10
|
357 return left;
|
rlm@10
|
358 else if(left instanceof Red)
|
rlm@10
|
359 {
|
rlm@10
|
360 if(right instanceof Red)
|
rlm@10
|
361 {
|
rlm@10
|
362 Node app = append(left.right(), right.left());
|
rlm@10
|
363 if(app instanceof Red)
|
rlm@10
|
364 return red(app.key, app.val(),
|
rlm@10
|
365 red(left.key, left.val(), left.left(), app.left()),
|
rlm@10
|
366 red(right.key, right.val(), app.right(), right.right()));
|
rlm@10
|
367 else
|
rlm@10
|
368 return red(left.key, left.val(), left.left(), red(right.key, right.val(), app, right.right()));
|
rlm@10
|
369 }
|
rlm@10
|
370 else
|
rlm@10
|
371 return red(left.key, left.val(), left.left(), append(left.right(), right));
|
rlm@10
|
372 }
|
rlm@10
|
373 else if(right instanceof Red)
|
rlm@10
|
374 return red(right.key, right.val(), append(left, right.left()), right.right());
|
rlm@10
|
375 else //black/black
|
rlm@10
|
376 {
|
rlm@10
|
377 Node app = append(left.right(), right.left());
|
rlm@10
|
378 if(app instanceof Red)
|
rlm@10
|
379 return red(app.key, app.val(),
|
rlm@10
|
380 black(left.key, left.val(), left.left(), app.left()),
|
rlm@10
|
381 black(right.key, right.val(), app.right(), right.right()));
|
rlm@10
|
382 else
|
rlm@10
|
383 return balanceLeftDel(left.key, left.val(), left.left(), black(right.key, right.val(), app, right.right()));
|
rlm@10
|
384 }
|
rlm@10
|
385 }
|
rlm@10
|
386
|
rlm@10
|
387 static Node balanceLeftDel(Object key, Object val, Node del, Node right){
|
rlm@10
|
388 if(del instanceof Red)
|
rlm@10
|
389 return red(key, val, del.blacken(), right);
|
rlm@10
|
390 else if(right instanceof Black)
|
rlm@10
|
391 return rightBalance(key, val, del, right.redden());
|
rlm@10
|
392 else if(right instanceof Red && right.left() instanceof Black)
|
rlm@10
|
393 return red(right.left().key, right.left().val(),
|
rlm@10
|
394 black(key, val, del, right.left().left()),
|
rlm@10
|
395 rightBalance(right.key, right.val(), right.left().right(), right.right().redden()));
|
rlm@10
|
396 else
|
rlm@10
|
397 throw new UnsupportedOperationException("Invariant violation");
|
rlm@10
|
398 }
|
rlm@10
|
399
|
rlm@10
|
400 static Node balanceRightDel(Object key, Object val, Node left, Node del){
|
rlm@10
|
401 if(del instanceof Red)
|
rlm@10
|
402 return red(key, val, left, del.blacken());
|
rlm@10
|
403 else if(left instanceof Black)
|
rlm@10
|
404 return leftBalance(key, val, left.redden(), del);
|
rlm@10
|
405 else if(left instanceof Red && left.right() instanceof Black)
|
rlm@10
|
406 return red(left.right().key, left.right().val(),
|
rlm@10
|
407 leftBalance(left.key, left.val(), left.left().redden(), left.right().left()),
|
rlm@10
|
408 black(key, val, left.right().right(), del));
|
rlm@10
|
409 else
|
rlm@10
|
410 throw new UnsupportedOperationException("Invariant violation");
|
rlm@10
|
411 }
|
rlm@10
|
412
|
rlm@10
|
413 static Node leftBalance(Object key, Object val, Node ins, Node right){
|
rlm@10
|
414 if(ins instanceof Red && ins.left() instanceof Red)
|
rlm@10
|
415 return red(ins.key, ins.val(), ins.left().blacken(), black(key, val, ins.right(), right));
|
rlm@10
|
416 else if(ins instanceof Red && ins.right() instanceof Red)
|
rlm@10
|
417 return red(ins.right().key, ins.right().val(),
|
rlm@10
|
418 black(ins.key, ins.val(), ins.left(), ins.right().left()),
|
rlm@10
|
419 black(key, val, ins.right().right(), right));
|
rlm@10
|
420 else
|
rlm@10
|
421 return black(key, val, ins, right);
|
rlm@10
|
422 }
|
rlm@10
|
423
|
rlm@10
|
424
|
rlm@10
|
425 static Node rightBalance(Object key, Object val, Node left, Node ins){
|
rlm@10
|
426 if(ins instanceof Red && ins.right() instanceof Red)
|
rlm@10
|
427 return red(ins.key, ins.val(), black(key, val, left, ins.left()), ins.right().blacken());
|
rlm@10
|
428 else if(ins instanceof Red && ins.left() instanceof Red)
|
rlm@10
|
429 return red(ins.left().key, ins.left().val(),
|
rlm@10
|
430 black(key, val, left, ins.left().left()),
|
rlm@10
|
431 black(ins.key, ins.val(), ins.left().right(), ins.right()));
|
rlm@10
|
432 else
|
rlm@10
|
433 return black(key, val, left, ins);
|
rlm@10
|
434 }
|
rlm@10
|
435
|
rlm@10
|
436 Node replace(Node t, Object key, Object val){
|
rlm@10
|
437 int c = doCompare(key, t.key);
|
rlm@10
|
438 return t.replace(t.key,
|
rlm@10
|
439 c == 0 ? val : t.val(),
|
rlm@10
|
440 c < 0 ? replace(t.left(), key, val) : t.left(),
|
rlm@10
|
441 c > 0 ? replace(t.right(), key, val) : t.right());
|
rlm@10
|
442 }
|
rlm@10
|
443
|
rlm@10
|
444 PersistentTreeMap(Comparator comp, Node tree, int count, IPersistentMap meta){
|
rlm@10
|
445 this._meta = meta;
|
rlm@10
|
446 this.comp = comp;
|
rlm@10
|
447 this.tree = tree;
|
rlm@10
|
448 this._count = count;
|
rlm@10
|
449 }
|
rlm@10
|
450
|
rlm@10
|
451 static Red red(Object key, Object val, Node left, Node right){
|
rlm@10
|
452 if(left == null && right == null)
|
rlm@10
|
453 {
|
rlm@10
|
454 if(val == null)
|
rlm@10
|
455 return new Red(key);
|
rlm@10
|
456 return new RedVal(key, val);
|
rlm@10
|
457 }
|
rlm@10
|
458 if(val == null)
|
rlm@10
|
459 return new RedBranch(key, left, right);
|
rlm@10
|
460 return new RedBranchVal(key, val, left, right);
|
rlm@10
|
461 }
|
rlm@10
|
462
|
rlm@10
|
463 static Black black(Object key, Object val, Node left, Node right){
|
rlm@10
|
464 if(left == null && right == null)
|
rlm@10
|
465 {
|
rlm@10
|
466 if(val == null)
|
rlm@10
|
467 return new Black(key);
|
rlm@10
|
468 return new BlackVal(key, val);
|
rlm@10
|
469 }
|
rlm@10
|
470 if(val == null)
|
rlm@10
|
471 return new BlackBranch(key, left, right);
|
rlm@10
|
472 return new BlackBranchVal(key, val, left, right);
|
rlm@10
|
473 }
|
rlm@10
|
474
|
rlm@10
|
475 public IPersistentMap meta(){
|
rlm@10
|
476 return _meta;
|
rlm@10
|
477 }
|
rlm@10
|
478
|
rlm@10
|
479 static abstract class Node extends AMapEntry{
|
rlm@10
|
480 final Object key;
|
rlm@10
|
481
|
rlm@10
|
482 Node(Object key){
|
rlm@10
|
483 this.key = key;
|
rlm@10
|
484 }
|
rlm@10
|
485
|
rlm@10
|
486 public Object key(){
|
rlm@10
|
487 return key;
|
rlm@10
|
488 }
|
rlm@10
|
489
|
rlm@10
|
490 public Object val(){
|
rlm@10
|
491 return null;
|
rlm@10
|
492 }
|
rlm@10
|
493
|
rlm@10
|
494 public Object getKey(){
|
rlm@10
|
495 return key();
|
rlm@10
|
496 }
|
rlm@10
|
497
|
rlm@10
|
498 public Object getValue(){
|
rlm@10
|
499 return val();
|
rlm@10
|
500 }
|
rlm@10
|
501
|
rlm@10
|
502 Node left(){
|
rlm@10
|
503 return null;
|
rlm@10
|
504 }
|
rlm@10
|
505
|
rlm@10
|
506 Node right(){
|
rlm@10
|
507 return null;
|
rlm@10
|
508 }
|
rlm@10
|
509
|
rlm@10
|
510 abstract Node addLeft(Node ins);
|
rlm@10
|
511
|
rlm@10
|
512 abstract Node addRight(Node ins);
|
rlm@10
|
513
|
rlm@10
|
514 abstract Node removeLeft(Node del);
|
rlm@10
|
515
|
rlm@10
|
516 abstract Node removeRight(Node del);
|
rlm@10
|
517
|
rlm@10
|
518 abstract Node blacken();
|
rlm@10
|
519
|
rlm@10
|
520 abstract Node redden();
|
rlm@10
|
521
|
rlm@10
|
522 Node balanceLeft(Node parent){
|
rlm@10
|
523 return black(parent.key, parent.val(), this, parent.right());
|
rlm@10
|
524 }
|
rlm@10
|
525
|
rlm@10
|
526 Node balanceRight(Node parent){
|
rlm@10
|
527 return black(parent.key, parent.val(), parent.left(), this);
|
rlm@10
|
528 }
|
rlm@10
|
529
|
rlm@10
|
530 abstract Node replace(Object key, Object val, Node left, Node right);
|
rlm@10
|
531
|
rlm@10
|
532 }
|
rlm@10
|
533
|
rlm@10
|
534 static class Black extends Node{
|
rlm@10
|
535 public Black(Object key){
|
rlm@10
|
536 super(key);
|
rlm@10
|
537 }
|
rlm@10
|
538
|
rlm@10
|
539 Node addLeft(Node ins){
|
rlm@10
|
540 return ins.balanceLeft(this);
|
rlm@10
|
541 }
|
rlm@10
|
542
|
rlm@10
|
543 Node addRight(Node ins){
|
rlm@10
|
544 return ins.balanceRight(this);
|
rlm@10
|
545 }
|
rlm@10
|
546
|
rlm@10
|
547 Node removeLeft(Node del){
|
rlm@10
|
548 return balanceLeftDel(key, val(), del, right());
|
rlm@10
|
549 }
|
rlm@10
|
550
|
rlm@10
|
551 Node removeRight(Node del){
|
rlm@10
|
552 return balanceRightDel(key, val(), left(), del);
|
rlm@10
|
553 }
|
rlm@10
|
554
|
rlm@10
|
555 Node blacken(){
|
rlm@10
|
556 return this;
|
rlm@10
|
557 }
|
rlm@10
|
558
|
rlm@10
|
559 Node redden(){
|
rlm@10
|
560 return new Red(key);
|
rlm@10
|
561 }
|
rlm@10
|
562
|
rlm@10
|
563 Node replace(Object key, Object val, Node left, Node right){
|
rlm@10
|
564 return black(key, val, left, right);
|
rlm@10
|
565 }
|
rlm@10
|
566
|
rlm@10
|
567 }
|
rlm@10
|
568
|
rlm@10
|
569 static class BlackVal extends Black{
|
rlm@10
|
570 final Object val;
|
rlm@10
|
571
|
rlm@10
|
572 public BlackVal(Object key, Object val){
|
rlm@10
|
573 super(key);
|
rlm@10
|
574 this.val = val;
|
rlm@10
|
575 }
|
rlm@10
|
576
|
rlm@10
|
577 public Object val(){
|
rlm@10
|
578 return val;
|
rlm@10
|
579 }
|
rlm@10
|
580
|
rlm@10
|
581 Node redden(){
|
rlm@10
|
582 return new RedVal(key, val);
|
rlm@10
|
583 }
|
rlm@10
|
584
|
rlm@10
|
585 }
|
rlm@10
|
586
|
rlm@10
|
587 static class BlackBranch extends Black{
|
rlm@10
|
588 final Node left;
|
rlm@10
|
589
|
rlm@10
|
590 final Node right;
|
rlm@10
|
591
|
rlm@10
|
592 public BlackBranch(Object key, Node left, Node right){
|
rlm@10
|
593 super(key);
|
rlm@10
|
594 this.left = left;
|
rlm@10
|
595 this.right = right;
|
rlm@10
|
596 }
|
rlm@10
|
597
|
rlm@10
|
598 public Node left(){
|
rlm@10
|
599 return left;
|
rlm@10
|
600 }
|
rlm@10
|
601
|
rlm@10
|
602 public Node right(){
|
rlm@10
|
603 return right;
|
rlm@10
|
604 }
|
rlm@10
|
605
|
rlm@10
|
606 Node redden(){
|
rlm@10
|
607 return new RedBranch(key, left, right);
|
rlm@10
|
608 }
|
rlm@10
|
609
|
rlm@10
|
610 }
|
rlm@10
|
611
|
rlm@10
|
612 static class BlackBranchVal extends BlackBranch{
|
rlm@10
|
613 final Object val;
|
rlm@10
|
614
|
rlm@10
|
615 public BlackBranchVal(Object key, Object val, Node left, Node right){
|
rlm@10
|
616 super(key, left, right);
|
rlm@10
|
617 this.val = val;
|
rlm@10
|
618 }
|
rlm@10
|
619
|
rlm@10
|
620 public Object val(){
|
rlm@10
|
621 return val;
|
rlm@10
|
622 }
|
rlm@10
|
623
|
rlm@10
|
624 Node redden(){
|
rlm@10
|
625 return new RedBranchVal(key, val, left, right);
|
rlm@10
|
626 }
|
rlm@10
|
627
|
rlm@10
|
628 }
|
rlm@10
|
629
|
rlm@10
|
630 static class Red extends Node{
|
rlm@10
|
631 public Red(Object key){
|
rlm@10
|
632 super(key);
|
rlm@10
|
633 }
|
rlm@10
|
634
|
rlm@10
|
635 Node addLeft(Node ins){
|
rlm@10
|
636 return red(key, val(), ins, right());
|
rlm@10
|
637 }
|
rlm@10
|
638
|
rlm@10
|
639 Node addRight(Node ins){
|
rlm@10
|
640 return red(key, val(), left(), ins);
|
rlm@10
|
641 }
|
rlm@10
|
642
|
rlm@10
|
643 Node removeLeft(Node del){
|
rlm@10
|
644 return red(key, val(), del, right());
|
rlm@10
|
645 }
|
rlm@10
|
646
|
rlm@10
|
647 Node removeRight(Node del){
|
rlm@10
|
648 return red(key, val(), left(), del);
|
rlm@10
|
649 }
|
rlm@10
|
650
|
rlm@10
|
651 Node blacken(){
|
rlm@10
|
652 return new Black(key);
|
rlm@10
|
653 }
|
rlm@10
|
654
|
rlm@10
|
655 Node redden(){
|
rlm@10
|
656 throw new UnsupportedOperationException("Invariant violation");
|
rlm@10
|
657 }
|
rlm@10
|
658
|
rlm@10
|
659 Node replace(Object key, Object val, Node left, Node right){
|
rlm@10
|
660 return red(key, val, left, right);
|
rlm@10
|
661 }
|
rlm@10
|
662
|
rlm@10
|
663 }
|
rlm@10
|
664
|
rlm@10
|
665 static class RedVal extends Red{
|
rlm@10
|
666 final Object val;
|
rlm@10
|
667
|
rlm@10
|
668 public RedVal(Object key, Object val){
|
rlm@10
|
669 super(key);
|
rlm@10
|
670 this.val = val;
|
rlm@10
|
671 }
|
rlm@10
|
672
|
rlm@10
|
673 public Object val(){
|
rlm@10
|
674 return val;
|
rlm@10
|
675 }
|
rlm@10
|
676
|
rlm@10
|
677 Node blacken(){
|
rlm@10
|
678 return new BlackVal(key, val);
|
rlm@10
|
679 }
|
rlm@10
|
680
|
rlm@10
|
681 }
|
rlm@10
|
682
|
rlm@10
|
683 static class RedBranch extends Red{
|
rlm@10
|
684 final Node left;
|
rlm@10
|
685
|
rlm@10
|
686 final Node right;
|
rlm@10
|
687
|
rlm@10
|
688 public RedBranch(Object key, Node left, Node right){
|
rlm@10
|
689 super(key);
|
rlm@10
|
690 this.left = left;
|
rlm@10
|
691 this.right = right;
|
rlm@10
|
692 }
|
rlm@10
|
693
|
rlm@10
|
694 public Node left(){
|
rlm@10
|
695 return left;
|
rlm@10
|
696 }
|
rlm@10
|
697
|
rlm@10
|
698 public Node right(){
|
rlm@10
|
699 return right;
|
rlm@10
|
700 }
|
rlm@10
|
701
|
rlm@10
|
702 Node balanceLeft(Node parent){
|
rlm@10
|
703 if(left instanceof Red)
|
rlm@10
|
704 return red(key, val(), left.blacken(), black(parent.key, parent.val(), right, parent.right()));
|
rlm@10
|
705 else if(right instanceof Red)
|
rlm@10
|
706 return red(right.key, right.val(), black(key, val(), left, right.left()),
|
rlm@10
|
707 black(parent.key, parent.val(), right.right(), parent.right()));
|
rlm@10
|
708 else
|
rlm@10
|
709 return super.balanceLeft(parent);
|
rlm@10
|
710
|
rlm@10
|
711 }
|
rlm@10
|
712
|
rlm@10
|
713 Node balanceRight(Node parent){
|
rlm@10
|
714 if(right instanceof Red)
|
rlm@10
|
715 return red(key, val(), black(parent.key, parent.val(), parent.left(), left), right.blacken());
|
rlm@10
|
716 else if(left instanceof Red)
|
rlm@10
|
717 return red(left.key, left.val(), black(parent.key, parent.val(), parent.left(), left.left()),
|
rlm@10
|
718 black(key, val(), left.right(), right));
|
rlm@10
|
719 else
|
rlm@10
|
720 return super.balanceRight(parent);
|
rlm@10
|
721 }
|
rlm@10
|
722
|
rlm@10
|
723 Node blacken(){
|
rlm@10
|
724 return new BlackBranch(key, left, right);
|
rlm@10
|
725 }
|
rlm@10
|
726
|
rlm@10
|
727 }
|
rlm@10
|
728
|
rlm@10
|
729
|
rlm@10
|
730 static class RedBranchVal extends RedBranch{
|
rlm@10
|
731 final Object val;
|
rlm@10
|
732
|
rlm@10
|
733 public RedBranchVal(Object key, Object val, Node left, Node right){
|
rlm@10
|
734 super(key, left, right);
|
rlm@10
|
735 this.val = val;
|
rlm@10
|
736 }
|
rlm@10
|
737
|
rlm@10
|
738 public Object val(){
|
rlm@10
|
739 return val;
|
rlm@10
|
740 }
|
rlm@10
|
741
|
rlm@10
|
742 Node blacken(){
|
rlm@10
|
743 return new BlackBranchVal(key, val, left, right);
|
rlm@10
|
744 }
|
rlm@10
|
745 }
|
rlm@10
|
746
|
rlm@10
|
747
|
rlm@10
|
748 static public class Seq extends ASeq{
|
rlm@10
|
749 final ISeq stack;
|
rlm@10
|
750 final boolean asc;
|
rlm@10
|
751 final int cnt;
|
rlm@10
|
752
|
rlm@10
|
753 public Seq(ISeq stack, boolean asc){
|
rlm@10
|
754 this.stack = stack;
|
rlm@10
|
755 this.asc = asc;
|
rlm@10
|
756 this.cnt = -1;
|
rlm@10
|
757 }
|
rlm@10
|
758
|
rlm@10
|
759 public Seq(ISeq stack, boolean asc, int cnt){
|
rlm@10
|
760 this.stack = stack;
|
rlm@10
|
761 this.asc = asc;
|
rlm@10
|
762 this.cnt = cnt;
|
rlm@10
|
763 }
|
rlm@10
|
764
|
rlm@10
|
765 Seq(IPersistentMap meta, ISeq stack, boolean asc, int cnt){
|
rlm@10
|
766 super(meta);
|
rlm@10
|
767 this.stack = stack;
|
rlm@10
|
768 this.asc = asc;
|
rlm@10
|
769 this.cnt = cnt;
|
rlm@10
|
770 }
|
rlm@10
|
771
|
rlm@10
|
772 static Seq create(Node t, boolean asc, int cnt){
|
rlm@10
|
773 return new Seq(push(t, null, asc), asc, cnt);
|
rlm@10
|
774 }
|
rlm@10
|
775
|
rlm@10
|
776 static ISeq push(Node t, ISeq stack, boolean asc){
|
rlm@10
|
777 while(t != null)
|
rlm@10
|
778 {
|
rlm@10
|
779 stack = RT.cons(t, stack);
|
rlm@10
|
780 t = asc ? t.left() : t.right();
|
rlm@10
|
781 }
|
rlm@10
|
782 return stack;
|
rlm@10
|
783 }
|
rlm@10
|
784
|
rlm@10
|
785 public Object first(){
|
rlm@10
|
786 return stack.first();
|
rlm@10
|
787 }
|
rlm@10
|
788
|
rlm@10
|
789 public ISeq next(){
|
rlm@10
|
790 Node t = (Node) stack.first();
|
rlm@10
|
791 ISeq nextstack = push(asc ? t.right() : t.left(), stack.next(), asc);
|
rlm@10
|
792 if(nextstack != null)
|
rlm@10
|
793 {
|
rlm@10
|
794 return new Seq(nextstack, asc, cnt - 1);
|
rlm@10
|
795 }
|
rlm@10
|
796 return null;
|
rlm@10
|
797 }
|
rlm@10
|
798
|
rlm@10
|
799 public int count(){
|
rlm@10
|
800 if(cnt < 0)
|
rlm@10
|
801 return super.count();
|
rlm@10
|
802 return cnt;
|
rlm@10
|
803 }
|
rlm@10
|
804
|
rlm@10
|
805 public Obj withMeta(IPersistentMap meta){
|
rlm@10
|
806 return new Seq(meta, stack, asc, cnt);
|
rlm@10
|
807 }
|
rlm@10
|
808 }
|
rlm@10
|
809
|
rlm@10
|
810 static public class NodeIterator implements Iterator{
|
rlm@10
|
811 Stack stack = new Stack();
|
rlm@10
|
812 boolean asc;
|
rlm@10
|
813
|
rlm@10
|
814 NodeIterator(Node t, boolean asc){
|
rlm@10
|
815 this.asc = asc;
|
rlm@10
|
816 push(t);
|
rlm@10
|
817 }
|
rlm@10
|
818
|
rlm@10
|
819 void push(Node t){
|
rlm@10
|
820 while(t != null)
|
rlm@10
|
821 {
|
rlm@10
|
822 stack.push(t);
|
rlm@10
|
823 t = asc ? t.left() : t.right();
|
rlm@10
|
824 }
|
rlm@10
|
825 }
|
rlm@10
|
826
|
rlm@10
|
827 public boolean hasNext(){
|
rlm@10
|
828 return !stack.isEmpty();
|
rlm@10
|
829 }
|
rlm@10
|
830
|
rlm@10
|
831 public Object next(){
|
rlm@10
|
832 Node t = (Node) stack.pop();
|
rlm@10
|
833 push(asc ? t.right() : t.left());
|
rlm@10
|
834 return t;
|
rlm@10
|
835 }
|
rlm@10
|
836
|
rlm@10
|
837 public void remove(){
|
rlm@10
|
838 throw new UnsupportedOperationException();
|
rlm@10
|
839 }
|
rlm@10
|
840 }
|
rlm@10
|
841
|
rlm@10
|
842 static class KeyIterator implements Iterator{
|
rlm@10
|
843 NodeIterator it;
|
rlm@10
|
844
|
rlm@10
|
845 KeyIterator(NodeIterator it){
|
rlm@10
|
846 this.it = it;
|
rlm@10
|
847 }
|
rlm@10
|
848
|
rlm@10
|
849 public boolean hasNext(){
|
rlm@10
|
850 return it.hasNext();
|
rlm@10
|
851 }
|
rlm@10
|
852
|
rlm@10
|
853 public Object next(){
|
rlm@10
|
854 return ((Node) it.next()).key;
|
rlm@10
|
855 }
|
rlm@10
|
856
|
rlm@10
|
857 public void remove(){
|
rlm@10
|
858 throw new UnsupportedOperationException();
|
rlm@10
|
859 }
|
rlm@10
|
860 }
|
rlm@10
|
861
|
rlm@10
|
862 static class ValIterator implements Iterator{
|
rlm@10
|
863 NodeIterator it;
|
rlm@10
|
864
|
rlm@10
|
865 ValIterator(NodeIterator it){
|
rlm@10
|
866 this.it = it;
|
rlm@10
|
867 }
|
rlm@10
|
868
|
rlm@10
|
869 public boolean hasNext(){
|
rlm@10
|
870 return it.hasNext();
|
rlm@10
|
871 }
|
rlm@10
|
872
|
rlm@10
|
873 public Object next(){
|
rlm@10
|
874 return ((Node) it.next()).val();
|
rlm@10
|
875 }
|
rlm@10
|
876
|
rlm@10
|
877 public void remove(){
|
rlm@10
|
878 throw new UnsupportedOperationException();
|
rlm@10
|
879 }
|
rlm@10
|
880 }
|
rlm@10
|
881 /*
|
rlm@10
|
882 static public void main(String args[]){
|
rlm@10
|
883 if(args.length != 1)
|
rlm@10
|
884 System.err.println("Usage: RBTree n");
|
rlm@10
|
885 int n = Integer.parseInt(args[0]);
|
rlm@10
|
886 Integer[] ints = new Integer[n];
|
rlm@10
|
887 for(int i = 0; i < ints.length; i++)
|
rlm@10
|
888 {
|
rlm@10
|
889 ints[i] = i;
|
rlm@10
|
890 }
|
rlm@10
|
891 Collections.shuffle(Arrays.asList(ints));
|
rlm@10
|
892 //force the ListMap class loading now
|
rlm@10
|
893 // try
|
rlm@10
|
894 // {
|
rlm@10
|
895 //
|
rlm@10
|
896 // //PersistentListMap.EMPTY.assocEx(1, null).assocEx(2,null).assocEx(3,null);
|
rlm@10
|
897 // }
|
rlm@10
|
898 // catch(Exception e)
|
rlm@10
|
899 // {
|
rlm@10
|
900 // e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
|
rlm@10
|
901 // }
|
rlm@10
|
902 System.out.println("Building set");
|
rlm@10
|
903 //IPersistentMap set = new PersistentArrayMap();
|
rlm@10
|
904 //IPersistentMap set = new PersistentHashtableMap(1001);
|
rlm@10
|
905 IPersistentMap set = PersistentHashMap.EMPTY;
|
rlm@10
|
906 //IPersistentMap set = new ListMap();
|
rlm@10
|
907 //IPersistentMap set = new ArrayMap();
|
rlm@10
|
908 //IPersistentMap set = new PersistentTreeMap();
|
rlm@10
|
909 // for(int i = 0; i < ints.length; i++)
|
rlm@10
|
910 // {
|
rlm@10
|
911 // Integer anInt = ints[i];
|
rlm@10
|
912 // set = set.add(anInt);
|
rlm@10
|
913 // }
|
rlm@10
|
914 long startTime = System.nanoTime();
|
rlm@10
|
915 for(Integer anInt : ints)
|
rlm@10
|
916 {
|
rlm@10
|
917 set = set.assoc(anInt, anInt);
|
rlm@10
|
918 }
|
rlm@10
|
919 //System.out.println("_count = " + set.count());
|
rlm@10
|
920
|
rlm@10
|
921 // System.out.println("_count = " + set._count + ", min: " + set.minKey() + ", max: " + set.maxKey()
|
rlm@10
|
922 // + ", depth: " + set.depth());
|
rlm@10
|
923 for(Object aSet : set)
|
rlm@10
|
924 {
|
rlm@10
|
925 IMapEntry o = (IMapEntry) aSet;
|
rlm@10
|
926 if(!set.contains(o.key()))
|
rlm@10
|
927 System.err.println("Can't find: " + o.key());
|
rlm@10
|
928 //else if(n < 2000)
|
rlm@10
|
929 // System.out.print(o.key().toString() + ",");
|
rlm@10
|
930 }
|
rlm@10
|
931
|
rlm@10
|
932 Random rand = new Random(42);
|
rlm@10
|
933 for(int i = 0; i < ints.length / 2; i++)
|
rlm@10
|
934 {
|
rlm@10
|
935 Integer anInt = ints[rand.nextInt(n)];
|
rlm@10
|
936 set = set.without(anInt);
|
rlm@10
|
937 }
|
rlm@10
|
938
|
rlm@10
|
939 long estimatedTime = System.nanoTime() - startTime;
|
rlm@10
|
940 System.out.println();
|
rlm@10
|
941
|
rlm@10
|
942 System.out.println("_count = " + set.count() + ", time: " + estimatedTime / 1000000);
|
rlm@10
|
943
|
rlm@10
|
944 System.out.println("Building ht");
|
rlm@10
|
945 Hashtable ht = new Hashtable(1001);
|
rlm@10
|
946 startTime = System.nanoTime();
|
rlm@10
|
947 // for(int i = 0; i < ints.length; i++)
|
rlm@10
|
948 // {
|
rlm@10
|
949 // Integer anInt = ints[i];
|
rlm@10
|
950 // ht.put(anInt,null);
|
rlm@10
|
951 // }
|
rlm@10
|
952 for(Integer anInt : ints)
|
rlm@10
|
953 {
|
rlm@10
|
954 ht.put(anInt, anInt);
|
rlm@10
|
955 }
|
rlm@10
|
956 //System.out.println("size = " + ht.size());
|
rlm@10
|
957 //Iterator it = ht.entrySet().iterator();
|
rlm@10
|
958 for(Object o1 : ht.entrySet())
|
rlm@10
|
959 {
|
rlm@10
|
960 Map.Entry o = (Map.Entry) o1;
|
rlm@10
|
961 if(!ht.containsKey(o.getKey()))
|
rlm@10
|
962 System.err.println("Can't find: " + o);
|
rlm@10
|
963 //else if(n < 2000)
|
rlm@10
|
964 // System.out.print(o.toString() + ",");
|
rlm@10
|
965 }
|
rlm@10
|
966
|
rlm@10
|
967 rand = new Random(42);
|
rlm@10
|
968 for(int i = 0; i < ints.length / 2; i++)
|
rlm@10
|
969 {
|
rlm@10
|
970 Integer anInt = ints[rand.nextInt(n)];
|
rlm@10
|
971 ht.remove(anInt);
|
rlm@10
|
972 }
|
rlm@10
|
973 estimatedTime = System.nanoTime() - startTime;
|
rlm@10
|
974 System.out.println();
|
rlm@10
|
975 System.out.println("size = " + ht.size() + ", time: " + estimatedTime / 1000000);
|
rlm@10
|
976
|
rlm@10
|
977 System.out.println("set lookup");
|
rlm@10
|
978 startTime = System.nanoTime();
|
rlm@10
|
979 int c = 0;
|
rlm@10
|
980 for(Integer anInt : ints)
|
rlm@10
|
981 {
|
rlm@10
|
982 if(!set.contains(anInt))
|
rlm@10
|
983 ++c;
|
rlm@10
|
984 }
|
rlm@10
|
985 estimatedTime = System.nanoTime() - startTime;
|
rlm@10
|
986 System.out.println("notfound = " + c + ", time: " + estimatedTime / 1000000);
|
rlm@10
|
987
|
rlm@10
|
988 System.out.println("ht lookup");
|
rlm@10
|
989 startTime = System.nanoTime();
|
rlm@10
|
990 c = 0;
|
rlm@10
|
991 for(Integer anInt : ints)
|
rlm@10
|
992 {
|
rlm@10
|
993 if(!ht.containsKey(anInt))
|
rlm@10
|
994 ++c;
|
rlm@10
|
995 }
|
rlm@10
|
996 estimatedTime = System.nanoTime() - startTime;
|
rlm@10
|
997 System.out.println("notfound = " + c + ", time: " + estimatedTime / 1000000);
|
rlm@10
|
998
|
rlm@10
|
999 // System.out.println("_count = " + set._count + ", min: " + set.minKey() + ", max: " + set.maxKey()
|
rlm@10
|
1000 // + ", depth: " + set.depth());
|
rlm@10
|
1001 }
|
rlm@10
|
1002 */
|
rlm@10
|
1003 }
|