简体   繁体   English

Java中的通用InternPool <T>?

[英]Generic InternPool<T> in Java?

How would I write a generic InternPool<T> in Java? 我如何用Java编写通用的InternPool<T> Does it need a Internable interface? 它需要一个Internable接口吗?

String in Java has interning capabilities; Java中的String具有实习功能; I want to intern classes like BigDecimal and Account . 我想要BigDecimalAccount等实习班。

Something like this: 像这样的东西:

public class InternPool<T> {

    private WeakHashMap<T, WeakReference<T>> pool = 
        new WeakHashMap<T, WeakReference<T>>();

    public synchronized T intern(T object) {
        T res = null;
        // (The loop is needed to deal with race
        // conditions where the GC runs while we are
        // accessing the 'pool' map or the 'ref' object.)
        do {
            WeakReference<T> ref = pool.get(object);
            if (ref == null) {
                ref = new WeakReference<T>(object);
                pool.put(object, ref);
                res = object;
            } else {
                res = ref.get();
            }
        } while (res == null);
        return res;
    }
}

This depends on the pool element class implementing the equals and hashCode to provide "equality by value" and to obey to the API contracts for those methods. 这取决于实现equalshashCode的pool元素类,以提供“按值相等”并遵守这些方法的API契约。 But BigDecimal certainly does. BigDecimal当然可以。


UPDATE - for an explanation of why we need a WeakHashMap<T, WeakReference<T>> rather than a WeakHashMap<T, T> , see the javadocs . 更新 - 为了解释为什么我们需要WeakHashMap<T, WeakReference<T>>而不是WeakHashMap<T, T> ,请参阅javadocs The short version is that the key weak-links in the latter won't be broken by the GC because the corresponding entry references are making the values strongly reachable. 简短版本是后者中的关键弱链接不会被GC破坏,因为相应的条目引用使得值可以很容易地到达。

For an example take a look at Interner from Guava . 举个例子来看看Guava的 Interner It does not require an Internable interface, it just relies on equals and hashCode . 不需要 Internable接口,它仅仅依赖于equalshashCode

I would separate the solution into two classes to have cleaner code and also this way getting rid of loop: 我会将解决方案分成两个类,以便有更清晰的代码,这样摆脱循环:

public class WeakPool<T> {
    private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();
    public T get(T object) {
        final T res;
        WeakReference<T> ref = pool.get(object);
        if (ref != null) {
            res = ref.get();
        } else {
            res = null;
        }
        return res;
    }
    public void put(T object) {
        pool.put(object, new WeakReference<T>(object));
    }
}

and the interning class using the weak pool is very simple: 使用弱池的实习类非常简单:

public class InternPool<T> {

    private final WeakPool<T> pool = new WeakPool<T>();

    public synchronized T intern(T object) {
        T res = pool.get(object);
        if (res == null) {
            pool.put(object);
            res = object;
        }
        return res;
    }
}

This more sounds like that you're looking for flyweight pattern . 这听起来更像你正在寻找飞重模式

Flyweight is a software design pattern. Flyweight是一种软件设计模式。 A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects flyweight是一种通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象

Click the link, it contains a Java example. 单击该链接,它包含一个Java示例。

Just a quick caveat: 只是一个快速警告:

It has not been explicitly mentioned above, but it should be obvious that the objects being interned must be of an immutable type. 它没有在上面明确提到过,但很明显被实例化的对象必须不可变类型。

On a second note: You don't need to use another weak reference to the object as the value in the map, a reference to a static would suffice if you just rely on the map's keyset for the data. 在第二个注释:您不需要使用对象的另一个弱引用作为映射中的值,如果您只依赖于数据的映射键集,则对静态的引用就足够了。 For example, declare: 例如,声明:

WeakHashMap<T,Boolean>

And insert pairs as: 并插入对:

pool.put (object, Boolean.TRUE);

Which is a minor saving of a WeakReference instance (if you can't reuse the one used for the key). 这是WeakReference实例的次要保存(如果您不能重用用于密钥的实例)。

...or create a WeakSet class, as @PeterVerhas has done with his WeakPool. ...或者创建一个WeakSet类,就像@PeterVerhas用他的WeakPool做的那样。

Shouldnt 不应该

"WeakReference ref = pool.get(object);" “WeakReference ref = pool.get(object);”

instead be 而是

WeakReference ref = pool.intern(object); WeakReference ref = pool.intern(object);

?? ??

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM