Good pattern for creating an object that supports interning?
I need a Class that supports interning, like Java's String
class. When creating an instance of the Class it should return a pre-existing reference if a reference with the same parameters already exists. Otherwise it should return a new refer开发者_JS百科ence. Such that:
Foo a = new Foo(5);
Foo b = new Foo(5);
Foo c = new Foo(6);
a == b
a != c
1) Is it the job of a factory to maintain the table of pre-existing objects, or is the table generally just a static variable within the class itself?
2) What is the table of pre-existing objects? Is it a Set of objects you search through every time an instance is requested, or is it a Map where keys are objects and values are parameters?
Two things come to my mind
Flyweight Pattern
Guava's ComputingMap
If you can add a third-party dependency consider Google Guava and its Interners class. It has two simple interners: a WeakInterner
and a StrongInterner
. The StrongInterner
is backed by a ConcurrentMap
and is best suited for a small, closed set of values. If you cannot control or in any way limit what is interned then you can opt for the WeakInterner
, which relies on WeakReference
s. The trade-off for using the WeakInterner
is performance.
You can't do this with the new
operator, which will not reuse an existing object. A factory is the best way to do this. (It can be as easy as a static newInstance
method of the class.) The usual data structure for this is a Map of some sort (typically a HashMap). A Set would be much more expensive. Depending on the number of objects, you could just use an array. (I think this might be what Byte does.)
Note that not a String objects are interned automatically, and that when you call intern
, it may return a different String instance. for instance, this code will print "false":
String a = new String("hello");
String b = new String("hello");
a.intern();
b.intern();
System.out.println(a == b ? "true" : "false");
精彩评论