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クラスが拡張 (または実装) する必要がある新しいクラスまたはインターフェイスを追加したことに注意してください。ここでの利点は、それがより慎重になり、将来のメンテナーの変更をまっすぐかつ狭く保つことです。選択するオブジェクト階層によって異なります。これにより、古いオブジェクトが作成されなくなりますEvictableString(おそらく、オブジェクトを削除可能にする必要があります。その場合、これは機能しません。)

ObjectBaseこれは、より適切な名前がインターフェースであるかどうか疑問に思いEvictableます。おそらく ...

EvictableObjectしかし、その親クラス (またはインターフェイス) を機能させるには、これが必要です。

public class EvictableObject<T extends ObjectBase>

もちろん、1行を次のように変更する必要があることに気づきました。

 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 に答える