1 21 22 27 28 package net.walend.somnifugi.sql92; 29 30 import java.lang.ref.Reference ; 31 import java.lang.ref.ReferenceQueue ; 32 import java.lang.ref.WeakReference ; 33 import java.util.AbstractCollection ; 34 import java.util.AbstractSet ; 35 import java.util.ArrayList ; 36 import java.util.Collection ; 37 import java.util.HashMap ; 38 import java.util.Iterator ; 39 import java.util.Map ; 40 import java.util.Set ; 41 42 class WeakValueHashMap 43 implements Map 44 { 45 String name = "Unknown"; 46 47 HashMap baseMap = new HashMap (); 48 51 private ReferenceQueue myqueue = new ReferenceQueue (); 52 53 WeakValueHashMap(String name) 54 { 55 super(); 56 this.name = name; 57 } 58 59 private void cleanupMap() 60 { 61 Object r; 62 63 while ( (r = myqueue.poll()) != null) 64 { 65 MyWeakValueReference wr = (MyWeakValueReference) r; 66 baseMap.remove(wr.getOriginalKey()); 67 } 68 69 } 70 @SuppressWarnings ("unchecked") 71 static class MyWeakValueReference extends java.lang.ref.WeakReference 72 { 73 Object mykey = null; 74 75 public MyWeakValueReference(Object key, Object value, ReferenceQueue q) 76 { 77 super(value,q); 78 this.mykey = key; 79 } 80 81 public int hashCode() 82 { 83 return mykey.hashCode(); 84 } 85 86 public Object getOriginalKey() 87 { 88 return mykey; 89 } 90 public String toString() 91 { 92 return mykey.toString(); 93 } 94 } 95 96 98 105 public int size() 106 { 107 cleanupMap(); 108 return baseMap.size(); 109 } 110 111 116 public boolean isEmpty() 117 { 118 cleanupMap(); 119 return baseMap.isEmpty(); 120 } 121 122 123 139 public boolean containsKey(Object key) 140 { 141 WeakReference k = (WeakReference )baseMap.get(key); 142 return k != null && !k.isEnqueued(); 143 } 144 145 161 public boolean containsValue(Object value) 162 { 163 cleanupMap(); 164 return baseMap.containsValue(value); 165 } 166 167 191 public Object get(Object key) 192 { 193 cleanupMap(); 194 Reference ref = (Reference )baseMap.get(key); 195 return (ref == null ? null : (ref.isEnqueued() ? null :ref.get())); 196 } 197 198 200 226 @SuppressWarnings ("unchecked") 227 public Object put(Object key, Object value) 228 { 229 cleanupMap(); 230 MyWeakValueReference ref = new MyWeakValueReference(key, value, myqueue); 231 WeakReference oldref = (WeakReference )baseMap.put(key, ref); 232 return (oldref == null ? null : (oldref.isEnqueued() ? null :oldref.get())); 233 } 234 235 260 public Object remove(Object key) 261 { 262 cleanupMap(); 263 WeakReference ref = (WeakReference )baseMap.remove(key); 264 return (ref == null ? null : ref.get()); 265 } 266 267 268 270 292 @SuppressWarnings ("unchecked") 293 public void putAll(Map t) 294 { 295 cleanupMap(); 296 baseMap.putAll(t); 297 } 298 299 305 public void clear() 306 { 307 cleanupMap(); 308 baseMap.clear(); 309 } 310 311 312 314 326 public Set keySet() 327 { 328 cleanupMap(); 329 return baseMap.keySet(); 330 } 331 332 345 private transient Collection values = null; 346 public Collection values() 347 { 348 cleanupMap(); 349 Collection vs = values; 350 return (vs != null ? vs : (values = new Values())); 351 } 352 353 private class ValueIterator implements Iterator 354 { 355 WeakReference next = null; 356 Iterator itr = null; 357 public ValueIterator(Iterator itr) 358 { 359 this.itr = itr; 360 } 361 362 public boolean hasNext() 363 { 364 if (next != null) 365 { 366 return true; 367 } 368 if (!itr.hasNext()) 369 { 370 return false; 371 } 372 next = (WeakReference )itr.next(); 373 while (next.isEnqueued()) 374 { 375 itr.remove(); 376 if (itr.hasNext()) 377 { 378 next = (WeakReference )itr.next(); 379 } 380 else 381 { 382 next = null; 383 break; 384 } 385 } 386 return next != null; 387 388 } 389 public Object next() 390 { 391 if (next == null) 392 { 393 if (!hasNext()) 394 { 395 return null; 396 } 397 } 398 while (next.isEnqueued()) 399 { 400 itr.remove(); 401 next = null; 402 if (! hasNext()) 403 { 404 break; 405 } 406 } 407 Object refval = (next == null ? null : next.get()); 408 next = null; 409 return refval; 410 } 411 412 public void remove() 413 { 414 itr.remove(); 415 } 416 } 417 418 private class Values extends AbstractCollection 419 { 420 public Iterator iterator() 421 { 422 return new ValueIterator(baseMap.values().iterator()); 423 } 424 425 public int size() 426 { 427 return WeakValueHashMap.this.size(); 428 } 429 430 public boolean contains(Object o) 431 { 432 return containsValue(o); 433 } 434 435 public void clear() 436 { 437 WeakValueHashMap.this.clear(); 438 } 439 @SuppressWarnings ("unchecked") 440 public Object [] toArray() 441 { 442 Collection c = new ArrayList (size()); 443 for (Iterator i = iterator(); i.hasNext(); ) 444 c.add(i.next()); 445 return c.toArray(); 446 } 447 @SuppressWarnings ("unchecked") 448 public Object [] toArray(Object a[]) 449 { 450 Collection c = new ArrayList (size()); 451 for (Iterator i = iterator(); i.hasNext(); ) 452 c.add(i.next()); 453 return c.toArray(a); 454 } 455 } 456 457 470 private transient Set entrySet = null; 471 public Set entrySet() 472 { 473 cleanupMap(); 474 Set vs = entrySet; 475 return (vs != null ? vs : (entrySet = new EntrySet())); 476 } 477 478 private class newEntryIterator implements Iterator 479 { 480 Map.Entry nextentry = null; 481 Iterator itr = null; 482 483 public newEntryIterator(Iterator itr) 484 { 485 this.itr = itr; 486 } 487 488 public boolean hasNext() 489 { 490 if (nextentry != null) 491 { 492 return true; 493 } 494 if (!itr.hasNext()) 495 { 496 return false; 497 } 498 Map.Entry mentry = (Map.Entry )itr.next(); 499 500 WeakReference nextref = (WeakReference )mentry.getValue(); 501 while (nextref.isEnqueued()) 502 { 503 itr.remove(); 504 mentry = (Map.Entry )itr.next(); 505 nextref = (WeakReference )mentry.getValue(); 506 } 507 if (nextref != null) 508 { 509 nextentry = new WeakValueEntry(mentry.getKey(), 510 nextref.get()); 511 } 512 return nextentry != null; 513 514 } 515 public Object next() 516 { 517 if (nextentry == null) 518 { 519 if (!hasNext()) 520 { 521 return null; 522 } 523 } 524 Object returnval = nextentry; 525 nextentry = null; 526 return returnval; 527 } 528 529 public void remove() 530 { 531 itr.remove(); 532 } 533 } 534 535 private class EntrySet extends AbstractSet 536 { 537 public Iterator iterator() 538 { 539 return new newEntryIterator(baseMap.entrySet().iterator()); 540 } 541 public boolean contains(Object o) 542 { 543 if (!(o instanceof Map.Entry )) 544 return false; 545 Map.Entry e = (Map.Entry )o; 546 return WeakValueHashMap.this.containsKey(e.getKey()); 547 } 548 public boolean remove(Object o) 549 { 550 if (!(o instanceof Map.Entry )) 551 return false; 552 Map.Entry e = (Map.Entry )o; 553 return WeakValueHashMap.this.remove(e.getKey()) != null; 554 } 555 public int size() 556 { 557 return WeakValueHashMap.this.size(); 558 } 559 public void clear() 560 { 561 WeakValueHashMap.this.clear(); 562 } 563 } 564 565 579 class WeakValueEntry implements Map.Entry 580 { 581 582 Object key = null; 583 Object value = null; 584 585 public WeakValueEntry(Object key, Object value) 586 { 587 this.key = key; 588 this.value = value; 589 } 590 591 596 public Object getKey() 597 { 598 return key; 599 } 600 601 602 609 public Object getValue() 610 { 611 return value; 612 } 613 614 633 public Object setValue(Object value) 634 { 635 throw new UnsupportedOperationException ("not supported"); 636 } 637 638 656 public boolean equals(Object o) 657 { 658 659 if (o instanceof Map.Entry ) 660 { 661 Map.Entry entry = (Map.Entry )o; 662 663 return (getKey()==null ? 664 entry.getKey()==null : getKey().equals(entry.getKey())) && 665 (getValue()==null ? 666 entry.getValue()==null : getValue().equals(entry.getValue())); 667 } 668 else 669 { 670 return super.equals(o); 671 } 672 } 673 674 690 public int hashCode() 691 { 692 return (getKey()==null ? 0 : getKey().hashCode()) ^ 693 (getValue()==null ? 0 : getValue().hashCode()); 694 } 695 } 696 697 699 711 public boolean equals(Object o) 712 { 713 cleanupMap(); 714 if (o instanceof WeakValueHashMap) 715 { 716 return baseMap.equals(((WeakValueHashMap)o).baseMap); 717 } 718 else 719 { 720 return baseMap.equals(o); 721 } 722 } 723 724 738 public int hashCode() 739 { 740 cleanupMap(); 741 return baseMap.hashCode(); 742 } 743 744 public static void main(String args[]) 745 { 746 WeakValueHashMap hm = new WeakValueHashMap("test"); 747 Object key1 = new Object (); 748 Object key2 = new Object (); 749 String value1 = new String ("value1"); 750 String value2 = new String ("value2"); 751 hm.put(key1, value1); 752 hm.put(key2, value2); 753 for (int i=0; i < 10; i ++) 754 { 755 System.gc(); 756 } 757 System.out.println("K1 get " + hm.get(key1)); 758 System.out.println("K2 get " + hm.get(key2)); 759 value2=null; 760 value1=null; 761 for (int i=0; i < 100; i ++) 762 { 763 System.gc(); 764 } 765 System.out.println("K1 get " + hm.get(key1)); 766 System.out.println("K2 get " + hm.get(key2)); 767 } 768 769 770 771 772 } 773 776 | Popular Tags |