Mercurial Hosting > nabble
diff src/fschmidt/util/java/Interner.java @ 68:00520880ad02
add fschmidt source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Sun, 05 Oct 2025 17:24:15 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fschmidt/util/java/Interner.java Sun Oct 05 17:24:15 2025 -0600 @@ -0,0 +1,65 @@ +package fschmidt.util.java; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentHashMap; + + +public final class Interner<T> { + + private static final class MyReference<T> extends WeakReference<T> { + private final int hash; + + MyReference(T t,ReferenceQueue<T> q) { + super(t,q); + hash = t.hashCode(); + } + + public boolean equals(Object obj) { + if( this==obj ) + return true; + if( !(obj instanceof MyReference) ) + return false; + MyReference ref = (MyReference)obj; + T t = this.get(); + if( t==null ) + return false; + return t.equals(ref.get()); + } + + public int hashCode() { + return hash; + } + } + + private final ConcurrentMap<MyReference<T>,MyReference<T>> map = new ConcurrentHashMap<MyReference<T>,MyReference<T>>(); + private ReferenceQueue<T> queue = new ReferenceQueue<T>(); + + private void sweep() { + while(true) { + Reference<? extends T> ref = queue.poll(); + if( ref == null ) + return; + map.remove(ref); + } + } + + public T intern(T t) { + MyReference<T> ref = new MyReference<T>(t,queue); + while(true) { + MyReference<T> ref2 = map.putIfAbsent(ref,ref); + if( ref2 == null ) { + sweep(); + return t; + } + T t2 = ref2.get(); + if( t2 != null ) { + ref.clear(); + return t2; + } + } + } + +}