簡體   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