通用 InternPool在Java中?

发布于 2024-09-11 08:57:51 字数 178 浏览 8 评论 0 原文

我如何用 Java 编写通用的 InternPool ?它需要一个Internable接口吗?

Java中的String具有interning能力;我想实习 BigDecimalAccount 等类。

How would I write a generic InternPool<T> in Java? Does it need a Internable interface?

String in Java has interning capabilities; I want to intern classes like BigDecimal and Account.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

〃温暖了心ぐ 2024-09-18 08:57:51

像这样的事情:

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;
    }
}

这取决于池元素类实现equalshashCode来提供“按值相等”并遵守这些方法的API契约。但 BigDecimal 确实如此。


更新 - 解释为什么我们需要 WeakHashMap> 而不是 WeakHashMap ,请参阅 javadocs。简而言之,后者的关键薄弱环节不会被 GC 破坏,因为相应的条目引用使值具有很强的可达性。

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. But BigDecimal certainly does.


UPDATE - for an explanation of why we need a WeakHashMap<T, WeakReference<T>> rather than a WeakHashMap<T, T>, see the 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.

白昼 2024-09-18 08:57:51

For an example take a look at Interner from Guava. It does not require an Internable interface, it just relies on equals and hashCode.

笑忘罢 2024-09-18 08:57:51

这听起来更像是您正在寻找 flyweight 模式

Flyweight是一种软件设计模式。享元是一种通过与其他类似对象共享尽可能多的数据来最小化内存使用的对象

单击链接,它包含一个 Java 示例。

This more sounds like that you're looking for flyweight pattern.

Flyweight is a software design pattern. A flyweight is an object that minimizes memory use by sharing as much data as possible with other similar objects

Click the link, it contains a Java example.

旧伤慢歌 2024-09-18 08:57:51

我会将解决方案分成两个类,以获得更清晰的代码,并且通过这种方式摆脱循环:

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));
    }
}

并且使用弱池的实习类非常简单:

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;
    }
}

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;
    }
}
长安忆 2024-09-18 08:57:51

只是一个快速警告:

上面没有明确提到,但很明显,被保留的对象必须不可变类型。

第二个注意事项:您不需要使用对该对象的另一个弱引用作为映射中的值,如果您仅依赖映射的键集来获取数据,则对静态的引用就足够了。例如,声明:

WeakHashMap<T,Boolean>

并将对插入为:

pool.put (object, Boolean.TRUE);

这是对 WeakReference 实例的少量节省(如果您无法重用用于键的实例)。

...或者创建一个 WeakSet 类,就像 @PeterVerhas 对他的 WeakPool 所做的那样。

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).

...or create a WeakSet class, as @PeterVerhas has done with his WeakPool.

踏雪无痕 2024-09-18 08:57:51

不应该

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

相反,

WeakReference ref = pool.intern(object);

??

Shouldnt

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

instead be

WeakReference ref = pool.intern(object);

??

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文