繁体   English   中英

创建自定义哈希表

[英]Create Custom Hashtable

我需要创建一个自定义哈希表扩展java.lang.Hashtable,并且我需要重写get方法以实现以下行为:

  1. 如果键== null,它将返回类型为V的新对象
  2. 如果super.get(key)== null,则还将返回一个V类型的新对象。

谁能帮我。 我尝试这样做,但我知道这是错误的。

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

知道错误发生在哪里。

您必须存储与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

这里的主要问题是您试图实现的目标基本上是错误的。 检出类的方法。 现在大多数将与get不一致。 更糟糕的是,未明确定义如何根据其他公共方法实现方法-继承的诅咒。

因此,创建一个代表您要实现的抽象的类。 不要让contain继承自适当的地图实现。

在这种情况下,自然映射可能不是旧的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 。)

为了创建,我假设了某种抽象工厂。 通常,方法没有无参数的公共构造函数,它们不会抛出异常。 当然要避免像猪流感与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)

您需要创建一个新实例吗? 还是返回默认实例就足够了?
后者可以像这样实现:

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

(但我仍然更喜欢乔恩的工厂解决方案:更灵活,并且涵盖了默认实例解决方案)

我了解您的要求,但请问以下内容:

  • 当键为null时,您是否总是想要一个新对象,还是只想允许null键?
  • 另外,当您找不到密钥时,您是否确实需要一个新实例,或者在每种情况下都找不到相同的实例?
  • 您是否要将新实例放入哈希表?
  • 它必须是Hashtable,还是HashMap可以呢?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM