2013-03-28 3 views
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) 

ли нет способа сделать это?

+1

Какие ошибки у вас возникают? –

+0

'ObjectA',' ObjectB' .... так далее..разные классы? и каждый из них ничего не расширяет? –

+0

@Lee Meador Я получаю: runEviction (java.util.Map ) в не может быть применен к (java.util.Map >) – loopkin

ответ

3

Попробуйте сделать общий метод runEviction.

private <T> void runEviction (Map<String, EvictableObject<T>> table) { 
+0

, который работал Спасибо, я не знал об этом синтаксисе. Спасибо за помощь – loopkin

2

Попробуйте добавить информацию о типе для метода runEviction:

private <T> void runEviction(Map<String, EvitcableObject<T>> table) {} 
+0

, которая сработала! Спасибо – loopkin

+1

В таком случае, примите ответ @rgettman. Он добрался до меня. – NilsH

1

Предыдущие ответы хороши. (+1 на обоих)

Но я хочу добавить несколько предложений. Возможно, мы можем спорить о них.

Обратите внимание, что я добавил новый класс или интерфейс ObjectBase, что все классы ObjectX должны расширять (или реализовывать). Преимущество здесь в том, что оно делает его более преднамеренным и сохраняет изменения будущего сопровождающего на прямом и узком уровне. Это зависит от вашей иерархии объектов, которую вы хотите выбрать. Это препятствует созданию любого старого объекта Evictable. (Возможно, вам нужно сделать String объекты evictable. В этом случае, это не будет работать.)

Это заставляет меня задаться вопросом, если лучшее название для ObjectBase будет Evictable является его интерфейс. Возможно ...

Но вам это нужно в 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(); 
    } 
+0

спасибо за подробный ответ. Я думал о том, чтобы мои выказываемые объекты реализовали интерфейс Evictable. Если это так, мне вообще не нужно будет использовать дженерики, я мог бы просто использовать EvictableObject , но мне это не нравится, потому что, по моему мнению, интерфейс Evictable ничего не приносит (по крайней мере, не мне). Если бы у него был способ выпускать некоторый ресурс, да, определенно. Но я предпочитаю не переопределять объект, когда это не требуется. – loopkin

Смежные вопросы