68
|
1 package fschmidt.util.java;
|
|
2
|
|
3 import java.lang.ref.Reference;
|
|
4 import java.lang.ref.ReferenceQueue;
|
|
5 import java.lang.ref.WeakReference;
|
|
6 import java.util.concurrent.ConcurrentMap;
|
|
7 import java.util.concurrent.ConcurrentHashMap;
|
|
8
|
|
9
|
|
10 public final class Interner<T> {
|
|
11
|
|
12 private static final class MyReference<T> extends WeakReference<T> {
|
|
13 private final int hash;
|
|
14
|
|
15 MyReference(T t,ReferenceQueue<T> q) {
|
|
16 super(t,q);
|
|
17 hash = t.hashCode();
|
|
18 }
|
|
19
|
|
20 public boolean equals(Object obj) {
|
|
21 if( this==obj )
|
|
22 return true;
|
|
23 if( !(obj instanceof MyReference) )
|
|
24 return false;
|
|
25 MyReference ref = (MyReference)obj;
|
|
26 T t = this.get();
|
|
27 if( t==null )
|
|
28 return false;
|
|
29 return t.equals(ref.get());
|
|
30 }
|
|
31
|
|
32 public int hashCode() {
|
|
33 return hash;
|
|
34 }
|
|
35 }
|
|
36
|
|
37 private final ConcurrentMap<MyReference<T>,MyReference<T>> map = new ConcurrentHashMap<MyReference<T>,MyReference<T>>();
|
|
38 private ReferenceQueue<T> queue = new ReferenceQueue<T>();
|
|
39
|
|
40 private void sweep() {
|
|
41 while(true) {
|
|
42 Reference<? extends T> ref = queue.poll();
|
|
43 if( ref == null )
|
|
44 return;
|
|
45 map.remove(ref);
|
|
46 }
|
|
47 }
|
|
48
|
|
49 public T intern(T t) {
|
|
50 MyReference<T> ref = new MyReference<T>(t,queue);
|
|
51 while(true) {
|
|
52 MyReference<T> ref2 = map.putIfAbsent(ref,ref);
|
|
53 if( ref2 == null ) {
|
|
54 sweep();
|
|
55 return t;
|
|
56 }
|
|
57 T t2 = ref2.get();
|
|
58 if( t2 != null ) {
|
|
59 ref.clear();
|
|
60 return t2;
|
|
61 }
|
|
62 }
|
|
63 }
|
|
64
|
|
65 }
|