创建自定义哈希表

时间:2009-04-29 09:00:14

标签: java generics hashtable

我需要创建一个Custom Hashtable extends java.lang.Hashtable,我需要覆盖get方法来实现以下行为:

  1. 如果key == null,它将返回V
  2. 类型的新对象
  3. 如果super.get(key)== null,它还将返回一个V类型的新对象。
  4. 任何人都可以帮助我。 我试着这样做,但我知道这是错的。

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

    请看行:

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

    和行:

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

    知道错误发生的位置..

4 个答案:

答案 0 :(得分:10)

您必须存储与V相关的类并创建新实例。例如:

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

(当然,您可能希望更改异常处理。)

另一种方法是让调用者有效地提供工厂来创建V的新实例。您可以使用以下界面执行此操作:

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

然后,您可以将工厂存储在自定义哈希表中,并在需要时随时调用create

答案 1 :(得分:3)

这里的主要问题是你想要实现的根本是错误的。查看班级的方法。其中大部分现在与get不一致。更糟糕的是,没有定义如何根据其他公共方法实现方法 - 这就是继承的诅咒。

因此,创建一个表示您尝试实现的抽象的类。让包含不从适当的地图实现继承。

在这种情况下,自然地图可能不是Hashtable而是java.util.concurrent.ConcurrentHashMap。这里重要的方法是[putIfAbsent] [2]。不幸的是,API文档很糟糕。以下是它应该如何使用:

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

(如果您想确保永不丢弃值,可以使用Future。)

创造我假设某种抽象工厂。通常,方法没有no-args公共构造函数,它们不会抛出异常。当然要避免像猪流感与H5N1交叉的反射。而是使用在创建时传入的适当的(抽象特定的)抽象工厂。

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)

答案 2 :(得分:2)

您是否需要创建新实例?或者是否足以返回默认实例?
后者可以实现如下:

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

(但我仍然更喜欢Jon的工厂解决方案:更灵活,也涵盖默认的实例解决方案)

答案 3 :(得分:0)

我理解你的要求,但我可以问下面的事情:

  • 当键为空时,您是否总是想要一个新对象,或者您不想只允许空键?
  • 另外,当你找不到密钥时,你肯定需要一个新的实例吗?或者在你找不到密钥的情况下,同一个实例会做什么?
  • 您是否要将新实例放入Hashtable?
  • 它必须是Hashtable,还是HashMap可以做?

我只是想知道您是否考虑过使用Apache Commons Collections中的LazyMap