2009-04-29 8 views
1

Je dois créer un Hashtable étend sur mesure java.lang.Hashtable et je dois remplacer la méthode get pour obtenir le comportement suivant:Créer personnalisé Hashtable

  1. si la clé == null, il retournera un nouvel objet du type V
  2. si la super.get (clé) == null, il retourne également un nouvel objet de type V.

quelqu'un peut-il me aider. J'essaie de le faire mais je sais que c'est faux.

import java.util.Hashtable; 

public class CustomHashtable<K, V> extends Hashtable { 
    @Override 
    public synchronized V get(Object key) { 
     if(key == null) return new Object(); 
     Object v = super.get(key); 
     if(v == null){ 
      return new Object(); 
     } 
    } 

} 

s'il vous plaît voir la ligne:

if(key == null) return new Object(); 

et les lignes:

if(v == null){ 
    return new Object(); 
} 

de savoir où l'erreur est survenue ..

+0

Qu'est-ce que * est * l'erreur? Je devine mais pouvez-vous être explicite? –

+0

L'erreur est erreur de syntaxe: Le type de retour de méthode est V, et j'essaie de retourner un type d'objet ... c'est l'erreur – Saeed

Répondre

10

Il faudrait stocker la classe lié à V et créer une nouvelle instance. Par exemple:

public class CustomHashtable<K, V> extends Hashtable { 
    Class<V> clazz; 

    public CustomHashtable(Class<V> clazz) { 
     this.clazz = clazz; 
    } 

    @Override 
    public synchronized V get(Object key) { 
     if(key == null) return newValue(); 
     Object v = super.get(key); 
     if(v == null){ 
      return newValue(); 
     } 
    } 

    private V newValue() { 
     try { 
      return clazz.newInstance(); 
     } catch (InstantiationException e) { 
      throw new RuntimeException (e); 
     } catch (IllegalAccessException e) { 
      throw new RuntimeException (e); 
     } 
    } 
} 

(Vous pouvez modifier la gestion des exceptions bien sûr.)

Une alternative est de faire l'appelant de fournir efficacement une usine pour créer une nouvelle instance de V. Tu ferais cela avec une interface telle que:

public interface Factory<T> { 
    T create(); 
} 

Vous pouvez ensuite stocker l'usine dans la table de hachage personnalisé, et appelez create tout moment vous avez besoin de.

+0

Ne leur dites pas d'utiliser la réflexion !!!!!!! eleventyone –

+0

Merci Jon Skeet beaucoup ... Votre aide sera appréciée .... Merci encore ... – Saeed

0

Je comprends ce que vous avez demandé, mais pourrais-je poser la question suivante s'il vous plaît:

  • Voulez-vous toujours un nouvel objet lorsque la clé est nulle, ou ne vous veulent pas seulement pour permettre une clé nulle?
  • De même, avez-vous vraiment besoin d'une nouvelle instance lorsque vous ne trouvez pas la clé, ou la même instance fera-t-elle dans chaque cas où vous ne trouvez pas la clé?
  • Allez-vous placer les nouvelles instances dans la table de hachage?
  • Est-ce que ce doit être une table de hachage ou un HashMap?

Je me demandais simplement si vous aviez envisagé d'utiliser un LazyMap de Apache Commons Collections?

+0

Merci A_M, l'idée de LazyMap est un bon aussi, je ne sais rien à ce sujet avant. Merci pour votre aide – Saeed

2

Avez-vous besoin de créer une nouvelle instance? ou est-ce suffisant pour renvoyer une instance par défaut?
Ce dernier pourrait être mis en œuvre comme:

public class CustomHashtable<K, V> extends Hashtable<K, V> { 

    /** Default instance. */ 
    private final V defaultValue; 

    public CustomHashtable(V defaultValue) { 
     this.defaultValue= defaultValue; 
    } 

    @Override 
    public synchronized V get(Object key) { 
     if(key != null) { 
      V val = super.get(key); 
      if(val != null) { 
       return val; 
      } 
     } 
     return defaultValue; 
    } 
} 

(mais je préfère encore la solution d'usine de Jon: plus souple et couvre également la solution d'instance par défaut)

+0

Merci Carlos Heuberger Votre idée est une bonne idée aussi ... Merci encore ... – Saeed

3

Le principal problème est ici ce que vous essayez d'atteindre est fondamentalement faussé. Vérifiez les méthodes de votre classe.La majorité d'entre eux seront maintenant incompatibles avec get. Pire, exactement comment les méthodes sont implémentées en termes d'autres méthodes publiques n'est pas définie - telle est la malédiction de l'héritage. Par conséquent, créez une classe qui représente n'importe quelle abstraction que vous essayez d'atteindre. Avoir le contenir pas hériter d'une implémentation de la carte appropriée.

La carte naturelle dans ce cas n'est probablement pas ye olde Hashtable mais java.util.concurrent.ConcurrentHashMap. La méthode importante ici est [putIfAbsent] [2]. Malheureusement, les docs de l'API sont nulles. Voici comment il doit être utilisé: (. Vous pouvez utiliser un Future si vous voulez vous assurer que vous ne défaussez une valeur)

public V getOrCreate(K key) { 
    final V value = map.get(key); 
    if (value != null) { 
     return value; 
    } 
    V newValue = factory.create(key); // May discard. 
    V oldValue = map.putIfAbsent(key, value); 
    return oldValue==null ? newValue : oldValue; 
} 

Pour créer, je l'ai supposé une sorte d'une usine abstraite . En général, les méthodes n'ont pas de constructeur public no-args qui n'arrive pas à lancer des exceptions. Évitez certainement la réflexion comme la grippe porcine croisée avec H5N1. Au lieu de cela, utilisez une fabrique abstraite appropriée (spécifique à l'abstraction) transmise au moment de la création.

public interface MySortOfFactory< 
    T /*extends SomeEntity*/, 
    A /*extends SomeInfo*/ 
> { 
    T create(A arg); 
} 

[2]: http://java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentMap.html#putIfAbsent(K, V)

Questions connexes