1

如果一段时间后未使用它们,我正在尝试使哈希图中的对象过期。

我有不同类型对象的映射,并希望使用泛型来处理它们以避免代码重复。

private Map<String,EvictableObject<ObjectA>> _objectsA = new HashMap<String,EvictableObject<ObjectA>> ();
private Map<String,EvictableObject<ObjectB>> _objectsB = new HashMap<String,EvictableObject<ObjectB>> ();
private Map<String,EvictableObject<ObjectC>> _objectsC = new HashMap<String,EvictableObject<ObjectC>> ();
private Map<String,EvictableObject<ObjectD>> _objectsD = new HashMap<String,EvictableObject<ObjectD>> ();


private void startEvictionTask() {

    Runnable evictionTask = new Runnable() {
        public void run () {
            runEviction(_objectsA);
            runEviction(_objectsB);
            runEviction(_objectsC);
            runEviction(_objectsD);
        }

        private void runEviction (Map<String, EvictableObject<?>> table) {

            final long expirationPeriod = 60 * 60 * 1000; // 60 minutes (in ms)

            synchronized (table) {
                for (Map.Entry<String,EvictableObject<? extends Object>> entry : table.entrySet()) {
                    if (entry.getValue().getAccessedSince() > expirationPeriod)
                        table.remove(entry.getKey());
                }
            }

        }
    };

    MyThreadPool.getScheduledExecutor().scheduleWithFixedDelay(evictionTask, 65*60, 5*60, TimeUnit.SECONDS);
}

但是我尝试过的所有方法似乎都不能作为 runEviction 方法的声明。并且编译器一直说实际参数不能转换为声明的方法参数。

我试过了:

private void runEviction (Map<String, EvictableObject<?>> table)

,

private void runEviction (Map<String, EvictableObject<B>> table)

,

private void runEviction (Map<String, EvictableObject<B extends Object>> table)

private void runEviction (Map<String, EvictableObject<? extends Object>> table)

有没有办法做到这一点?

4

3 回答 3

3

尝试使runEviction方法通用。

private <T> void runEviction (Map<String, EvictableObject<T>> table) {
于 2013-03-28T18:53:15.793 回答
2

尝试将类型信息添加到 runEviction 方法:

private <T> void runEviction(Map<String, EvitcableObject<T>> table) {}
于 2013-03-28T18:54:08.717 回答
1

前面的答案很好。(两者都+1)

但我想补充几点建议。也许我们可以争论它们。

ObjectBase请注意,我添加了一个所有ObjectX类都必须扩展(或实现)的新类或接口。这里的好处是它使它更加深思熟虑,并使未来维护者的更改保持直截了当。它确实取决于您要选择的对象层次结构。这样可以避免制造任何旧物体Evictable。(也许您需要使String对象可驱逐。在这种情况下,这将不起作用。)

这让我想知道是否更好的名称ObjectBaseEvictable它是一个接口。大概 ...

但是你需要这个EvictableObject来使父类(或接口)的东西工作:

public class EvictableObject<T extends ObjectBase>

当然,您已经注意到您必须将这一行更改为:

 for (Map.Entry<String,EvictableObject<T>> entry : table.entrySet()) 

因为T那里需要。

完整的新代码在这里。

    private Map<String,EvictableObject<ObjectA>> _objectsA = new HashMap<String,EvictableObject<ObjectA>> ();
    private Map<String,EvictableObject<ObjectB>> _objectsB = new HashMap<String,EvictableObject<ObjectB>> ();
    private Map<String,EvictableObject<ObjectC>> _objectsC = new HashMap<String,EvictableObject<ObjectC>> ();
    private Map<String,EvictableObject<ObjectD>> _objectsD = new HashMap<String,EvictableObject<ObjectD>> ();

    private void startEvictionTask() {

        Runnable evictionTask = new Runnable() {
            public void run () {
                runEviction(_objectsA);
                runEviction(_objectsB);
                runEviction(_objectsC);
                runEviction(_objectsD);
            }

            private <T extends ObjectBase> void runEviction (Map<String, EvictableObject<T>> table) {

                final long expirationPeriod = 60 * 60 * 1000; // 60 minutes (in ms)

                synchronized (table) {
                    for (Map.Entry<String,EvictableObject<T>> entry : table.entrySet()) {
                        if (entry.getValue().getAccessedSince() > expirationPeriod)
                            table.remove(entry.getKey());
                    }
                }

            }
        };

        new Thread(evictionTask).start();
    }
于 2013-03-28T19:56:50.650 回答