簡體   English   中英

哈希由兩個值組成的哈希元素中的查找元素

[英]Lookup elements in Hash where the key is composed of two values

我必須從數據庫中檢索以下結構:

    User ID
    User Name
    First Name
    Last Name
    Employee Number

這些字段我會將它們存儲在內存中以便快速訪問,換句話說就是緩存。 我們正在談論平均30萬條記錄。

我的問題是,我必須創建一個用於快速查詢的結構,有時按用戶名,有時按雇員編號。 永遠不要通過用戶ID,只能通過前面提到的兩個字段。

在詞典中,我受制於“一鍵通”原則,所以...

-是否有一種方法可以創建將用戶名和員工編號結合在一起以在詞典中使用的密鑰?

這里的問題是,有時我會獲得用戶指定的用戶名以進行查找,有時我會獲得員工編號,但永遠不會同時使用。

因此,假設該密鑰說MyKey(“ user-name”,“”)和MyKey(“”,“ employee-number”)應該從映射中檢索相同的注冊表。

我想避免在內存中創建兩個詞典,一個通過用戶名搜索,另一個通過員工編號搜索?

一種替代方法是將來自數據庫的結果存儲在一個大列表中,然后使用Linq查詢。 但是,這將是對O(n)的搜索,我們在這里討論性能。

您有以下選擇:

  1. 兩本字典
  2. 多字典(從未使用過,但看起來非常有用)
  3. 直接訪問數據庫

選擇可能取決於在典型情況下測試每個解決方案。 需要實驗的努力。

所以我解決了創建帶有Type和Value的Key對象的問題。

/// <summary>
/// Represents a composite key for cached objects
/// </summary>
public class MultiKey
{
    /// <summary>
    /// The type of key
    /// </summary>
    public enum Type
    {
        /// <summary>
        /// The key represents a User Name
        /// </summary>
        UserName,

        /// <summary>
        /// The key represents an Employee Number
        /// </summary>
        EmployeeNumber
    }

    /// <summary>
    /// Gets or sets the Type of the Key.
    /// </summary>
    public Type KeyType { get; set; }

    /// <summary>
    /// Gets or sets the value of the Key
    /// </summary>
    public string Key { get; set; }

    /// <summary>
    /// Compare based on hash code
    /// </summary>
    /// <param name="obj">the object to compare against</param>
    /// <returns>true if both objects are equals, false otherwise</returns>
    public override bool Equals(object obj)
    {
        if (obj is FormCacheKey)
        {
            return (obj as FormCacheKey).GetHashCode() == this.GetHashCode();
        }

        return false;
    }

    /// <summary>
    /// Compares based on hash code
    /// </summary>
    /// <param name="p1">left side of the operator</param>
    /// <param name="p2">right side of the operator</param>
    /// <returns>true if both items are equal, false otherwise</returns>
    public static bool operator ==(FormCacheKey p1, FormCacheKey p2)
    {
        if ((object)p1 == null && (object)p2 == null)
        {
            return true;
        }
        if ((object)p1 == null || (object)p2 == null)
        {
            return false;
        }
        return p1.Equals(p2);
    }

    /// <summary>
    /// Compares based on hash code
    /// </summary>
    /// <param name="p1">left side of the operator</param>
    /// <param name="p2">right side of the operator</param>
    /// <returns>true if both items are different, false otherwise</returns>
    public static bool operator !=(FormCacheKey p1, FormCacheKey p2)
    {
        return !(p1 == p2);
    }

    /// <summary>
    /// Returns a hash key code that identifies this object
    /// </summary>
    /// <returns>The hash code.</returns>
    public override int GetHashCode()
    {
        const int CoPrimeNumber = 37;
        var finalHashCode = 17;

        finalHashCode = (finalHashCode * CoPrimeNumber) + this.KeyType.GetHashCode();
        finalHashCode = (finalHashCode * CoPrimeNumber) + this.Key.GetHashCode();

        return finalHashCode;
    }
}

之后,我創建了一個字典

var cache = new Dictionary<MultiKey, User>();

最后,我將自己的鍵和值添加到字典中,如下所示:

foreach (var user in users)
{
    var userNameKey = new MultiKey { KeyType = MultiKey.Type.UserName, Key = user.UserName };
    cache.Add(userNameKey, user);
    var employeeNumberKey = new MultiKey { KeyType = MultiKey.Type.EmployeeNumber, Key = user.EmployeeNumber };
    cache.Add(employeeNumberKey, user);
}

性能說明與同事交談時,他捍衛了兩個哈希表技術,而不是我與MultiKey一起使用的方法。 他爭辯說,與帶有復雜鍵的單個緩存相比,在帶有兩個長叉哈希的字符串鍵進行搜索(訪問)期間的性能“更快”或“更高效”。 他的論點是,當緩存更大/更復雜時,沖突往往會更多。 我想聽聽您的意見。 最后,我使用了這種方法,並且有效。

為了訪問cahe中的項目,有必要提供MultiKey對象或重新創建它的方法。 從這個意義上講,我創建了以下輔助方法

private T GetFromCache<T>(CacheKey.Type type, string key)
{
    var cKey = new MultiKey { KeyType = type, Key = key };
    T item;
    cache.TryGetValue(cKey, out item);

    return item;
}

我這樣使用它:

public User GetUserByUserName(string userName)
{
    return this.GetFromDictionary<User>(MultiKey.Type.UserName, userName);
}

public User GetIndividualByEmployeeNumber(string employeeNumber)
{
    return this.GetFromDictionary<User>(MultiKey.Type.EmployeeNumber, employeeNumber);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM