简体   繁体   English

创建自定义哈希表

[英]Create Custom Hashtable

I need to create a Custom Hashtable extends java.lang.Hashtable and i need to override the get method to achieve the following behavior : 我需要创建一个自定义哈希表扩展java.lang.Hashtable,并且我需要重写get方法以实现以下行为:

  1. if the key == null, it will return a new object of the type V 如果键== null,它将返回类型为V的新对象
  2. if the super.get(key) == null, it will also return a new object of type V. 如果super.get(key)== null,则还将返回一个V类型的新对象。

Can anyone help me. 谁能帮我。 I try to do this but I know it's wrong. 我尝试这样做,但我知道这是错误的。

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

}

please see the line : 请看这行:

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

and the lines : 和线:

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

to know where the error occurred.. 知道错误发生在哪里。

You'd have to store the class related to V and create a new instance. 您必须存储与V相关的类并创建一个新实例。 For example: 例如:

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

(You may want to change the exception handling of course.) (您当然可以更改异常处理。)

An alternative is to make the caller effectively provide a factory to create a new instance of V . 一种替代方法是使调用方有效地提供一个工厂来创建V的新实例。 You'd do this with an interface such as: 您可以使用以下接口进行此操作:

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

You could then store the factory in the custom hashtable, and call create any time you needed to. 然后,您可以将工厂存储在自定义哈希表中,并在需要时随时调用create

The primary issue here is what you are trying to achieve is fundamentally wrongheaded. 这里的主要问题是您试图实现的目标基本上是错误的。 Checkout the methods of your class. 检出类的方法。 The majority of them will now be inconsistent with get . 现在大多数将与get不一致。 Worse, exactly how methods are implemented in terms of other public methods is not defined - such is the curse of inheritance. 更糟糕的是,未明确定义如何根据其他公共方法实现方法-继承的诅咒。

Therefore, create a class that represents whatever abstraction you are trying to achieve. 因此,创建一个代表您要实现的抽象的类。 Have the contain not inherit from an appropriate map implementation. 不要让contain继承自适当的地图实现。

The natural map in this case is probably not ye olde Hashtable but java.util.concurrent.ConcurrentHashMap . 在这种情况下,自然映射可能不是旧的Hashtable而是java.util.concurrent.ConcurrentHashMap The important method here is [ putIfAbsent ][2]. 这里的重要方法是[ putIfAbsent ] [2]。 Unfortunately the API docs suck. 不幸的是,API文档很烂。 Here is how it should be used: 这是应如何使用:

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

(You can use a Future if you want to ensure that you never discard a value.) (如果要确保您永远不会丢弃值,则可以使用Future 。)

To create I've assumed some kind of an abstract factory. 为了创建,我假设了某种抽象工厂。 In general methods don't have no-args public constructors that happen not to throw exceptions. 通常,方法没有无参数的公共构造函数,它们不会抛出异常。 Certainly avoid reflection like swine flu crossed with H5N1. 当然要避免像猪流感与H5N1交叉感染那样的反射。 Instead use an appropriate (abstraction-specific) abstract factory passed in at creation time. 而是使用在创建时传入的适当的(特定于抽象的)抽象工厂。

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]: http : //java.sun.com/javase/6/docs/api/java/util/concurrent/ConcurrentMap.html#putIfAbsent(K ,V)

Do you need to create a new instance? 您需要创建一个新实例吗? or is it sufficient to return a default instance? 还是返回默认实例就足够了?
The latter could be implemented like: 后者可以像这样实现:

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

(but I still prefer Jon's factory solution: more flexible and also covers the default instance solution) (但我仍然更喜欢乔恩的工厂解决方案:更灵活,并且涵盖了默认实例解决方案)

I understand what you asked, but could I ask the following please: 我了解您的要求,但请问以下内容:

  • Do you always want a new object when the key is null, or don't you just want to allow a null key? 当键为null时,您是否总是想要一个新对象,还是只想允许null键?
  • Also, do you definitely need a new instance when you can't find the key, or will the same instance do in each case where you can't find the key? 另外,当您找不到密钥时,您是否确实需要一个新实例,或者在每种情况下都找不到相同的实例?
  • Are you going to put the new instances into the Hashtable? 您是否要将新实例放入哈希表?
  • Does it have to be a Hashtable, or could a HashMap do? 它必须是Hashtable,还是HashMap可以呢?

I'm just wondering if you had considered using a LazyMap from Apache Commons Collections? 我只是想知道您是否考虑过使用Apache Commons Collections中的LazyMap

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

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