KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > mbeanserver > WeakIdentityHashMap


1 /*
2  * @(#)WeakIdentityHashMap.java 1.2 05/11/17
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.mbeanserver;
9
10 import static com.sun.jmx.mbeanserver.Util.*;
11
12 import java.lang.ref.Reference JavaDoc;
13 import java.lang.ref.ReferenceQueue JavaDoc;
14 import java.lang.ref.WeakReference JavaDoc;
15
16 import java.util.Map JavaDoc;
17
18
19 /**
20  * <p>A map where keys are compared using identity comparison (like
21  * IdentityHashMap) but where the presence of an object as a key in
22  * the map does not prevent it being garbage collected (like
23  * WeakHashMap). This class does not implement the Map interface
24  * because it is difficult to ensure correct semantics for iterators
25  * over the entrySet().</p>
26  *
27  * <p>Because we do not implement Map, we do not copy the questionable
28  * interface where you can call get(k) or remove(k) for any type of k,
29  * which of course can only have an effect if k is of type K.</p>
30  *
31  * <p>This map does not support null keys.</p>
32  */

33 /*
34  * The approach
35  * is to wrap each key in a WeakReference and use the wrapped value as
36  * a key in an ordinary HashMap. The WeakReference has to be a
37  * subclass IdentityWeakReference (IWR) where two IWRs are equal if
38  * they refer to the same object. This enables us to find the entry
39  * again.
40  */

41 class WeakIdentityHashMap<K, V> {
42     private WeakIdentityHashMap() {}
43     
44     static <K, V> WeakIdentityHashMap<K, V> make() {
45         return new WeakIdentityHashMap<K, V>();
46     }
47     
48     V get(K key) {
49     expunge();
50     WeakReference JavaDoc<K> keyref = makeReference(key);
51     return map.get(keyref);
52     }
53
54     public V put(K key, V value) {
55     expunge();
56     if (key == null)
57         throw new IllegalArgumentException JavaDoc("Null key");
58     WeakReference JavaDoc<K> keyref = makeReference(key, refQueue);
59     return map.put(keyref, value);
60     }
61
62     public V remove(K key) {
63     expunge();
64     WeakReference JavaDoc<K> keyref = makeReference(key);
65     return map.remove(keyref);
66     }
67
68     private void expunge() {
69     Reference JavaDoc<? extends K> ref;
70     while ((ref = refQueue.poll()) != null)
71         map.remove(ref);
72     }
73
74     private WeakReference JavaDoc<K> makeReference(K referent) {
75     return new IdentityWeakReference<K>(referent);
76     }
77
78     private WeakReference JavaDoc<K> makeReference(K referent, ReferenceQueue JavaDoc<K> q) {
79     return new IdentityWeakReference<K>(referent, q);
80     }
81
82     /**
83      * WeakReference where equals and hashCode are based on the
84      * referent. More precisely, two objects are equal if they are
85      * identical or if they both have the same non-null referent. The
86      * hashCode is the value the original referent had. Even if the
87      * referent is cleared, the hashCode remains. Thus, objects of
88      * this class can be used as keys in hash-based maps and sets.
89      */

90     private static class IdentityWeakReference<T> extends WeakReference JavaDoc<T> {
91     IdentityWeakReference(T o) {
92         this(o, null);
93     }
94
95     IdentityWeakReference(T o, ReferenceQueue JavaDoc<T> q) {
96         super(o, q);
97         this.hashCode = (o == null) ? 0 : System.identityHashCode(o);
98     }
99
100     public boolean equals(Object JavaDoc o) {
101         if (this == o)
102         return true;
103         if (!(o instanceof IdentityWeakReference))
104         return false;
105         IdentityWeakReference wr = (IdentityWeakReference) o;
106         Object JavaDoc got = get();
107         return (got != null && got == wr.get());
108     }
109
110     public int hashCode() {
111         return hashCode;
112     }
113
114     private final int hashCode;
115     }
116
117     private Map JavaDoc<WeakReference JavaDoc<K>, V> map = newMap();
118     private ReferenceQueue JavaDoc<K> refQueue = new ReferenceQueue JavaDoc<K>();
119 }
120
Popular Tags