2013-05-01 70 views
0

我有一個應用程序接收某些「事件」,由12個字符串和一個DateTime唯一標識。在每個事件都關聯一個字符串的結果。 我需要將這些事件保存在內存中(例如最多8小時),並且如果我再次收到同一事件,能夠知道我已經收到它(在過去的8小時內)。 要存儲的事件將小於1000. 我不能使用外部存儲器,它必須在內存中完成。帶日期時間+字符串鍵的目錄,並自動刪除舊條目

我的想法是使用一個字典,其中的鍵是一個由字符串和日期時間組成的類,該值是結果。

編輯:字符串本身(實際上是MAC地址)不能唯一標識事件,它是MAC和DateTime,這兩個組合是唯一的,這就是爲什麼密鑰必須由兩者組成。 應用程序是一個從客戶端接收特定事件的服務器:該事件在客戶端由客戶端MAC和客戶端日期時間標記(不能使用guid)。 可能發生客戶端重新傳輸相同的數據,並通過檢查MAC /日期時間密鑰的字典,我會知道我已經收到該數據。

然後,每隔一小時(例如),我可以對整個集合進行foreach並刪除datetime超過8小時的所有關鍵字。

你可以提出一個更好的方法來解決問題或我選擇的數據格式嗎?在代碼的性能和清潔方面。 或者更好的方式來刪除舊數據,例如LINQ。

謝謝, 馬蒂亞

+1

你的意思解釋?目錄聽起來像*會使用外部存儲。 – 2013-05-01 16:18:21

+0

哦,上帝,謝謝...是字典當然... – 2013-05-01 16:36:30

+0

爲什麼字符串和日期時間是unqiue?那麼在你的收藏中,這個字符串可以多次出現? – 2013-05-01 16:55:40

回答

0

我會去一個字典。

這樣你可以非常快速地搜索字符串(O(1)-operation)。

其他藏品慢:

  • OrderedDictionary:是緩慢的,因爲它需要裝箱和拆箱。
  • SortedDictionary:執行O(log n)操作。
  • 所有正常的數組和列表:使用O(n/2)操作。

一個例子:

public class Event 
{ 
    public Event(string macAddress, DateTime time, string data) 
    { 
     MacAddress = macAddress; 
     Time = time; 
     Data = data; 
    } 

    public string MacAddress { get; set; } 
    public DateTime Time { get; set; } 
    public string Data { get; set; } 
} 

public class EventCollection 
{ 
    private readonly Dictionary<Tuple<string, DateTime>, Event> _Events = new Dictionary<Tuple<string, DateTime>, Event>(); 

    public void Add(Event e) 
    { 
     _Events.Add(new Tuple<string, DateTime>(e.MacAddress, e.Time), e); 
    } 

    public IList<Event> GetOldEvents(bool autoRemove) 
    { 
     DateTime old = DateTime.Now - TimeSpan.FromHours(8); 
     List<Event> results = new List<Event>(); 
     foreach(Event e in _Events.Values) 
      if (e.Time < old) 
       results.Add(e); 

     // Clean up 
     if (autoRemove) 
      foreach(Event e in results) 
       _Events.Remove(new Tuple<string, DateTime>(e.MacAddress, e.Time)); 

     return results; 
    } 
} 
+0

有趣,但在每個事件都有一個值,我必須存儲在字典中(我有三個元素:字符串(MAC),日期時間,字符串(事件的值))。 此外,與您的詞典,我該如何清理詞典並刪除所有8小時以前的日期時間? – 2013-05-01 17:22:26

+0

我用一個例子更新了我的答案。 – 2013-05-01 17:25:30

+0

非常感謝這個書面例子,但正如我在之前的評論中所說的,我必須處理我的詞典中的3個元素: string(MAC),datetime和另一個字符串,它是事件的值。 所以我的活動可以有「AABBCCDDEEFF」,2013-05-01T12:13:15,「活動的價值」。 有了您的解決方案,我可以在哪裏存儲「事件的價值」? 謝謝 – 2013-05-01 17:47:27

0

其中鍵是12人物造型標識符和所述結果和日期時間是該值的一部分,我會用一個OrderedDictionary。可悲OrderedDictionary是不通用的(鍵和值是對象),所以你需要做自己的鑄造和類型檢查。當您需要刪除舊事件時,您可以通過OrderedDictionary進行foreach,並在您達到足夠新的時間時停止。這假設您使用的日期時間是將它們添加到字典中。

+0

我編輯了這個問題,也許我還不清楚爲什麼日期時間必須在關鍵。 並且不,事件的日期不一定會按順序排列。 – 2013-05-01 16:49:02

+0

啊,好的。如果日期時間不符合規定,我不會使用OrderedDicationary。就像達克斯說的那樣,這種方法需要在每次插入後重新排序,如果只有1000個左右事件,則不會節省那麼多時間。 – Cemafor 2013-05-01 16:57:48

1

活動時間必須到而不是成爲關鍵的一部分 - 如果是,您如何能夠告訴您已經收到此活動?所以你應該移動到一個字典,其中的鍵是事件名稱,值是日期和結果的元組。

在一段時間後,你可以從字典中很容易與LINQ修剪舊數據:

dictionary = dictionary 
    .Where(p => p.Value.DateOfEvent >= DateTime.Now.AddHours(-8)) 
    .ToDictionary(); 
+0

我編輯了這個問題,也許我還不清楚爲什麼datetime必須在關鍵字中。 – 2013-05-01 16:53:21

+0

非常好的解決方案來刪除舊數據,但如果我選擇字典<元組<字符串,DateTime>,事件>解決方案來存儲數據,是否有可能調整您的解決方案來檢查Tuple鍵中的DateTime p.Value.DateOfEvent的? – 2013-05-01 18:33:12

+0

@MattiaDurli:當然 - 't => t.Item2.DateOfEvent> = ...',或者您決定保留日期的任何項目號。 – Jon 2013-05-01 21:33:52

1

如果要求規定,每小時更新一次就足夠好,你永遠有超過1000個項目字典,你的解決方案應該是完全足夠的,並且可能是任何其他人看到你的代碼最容易理解的。我可能會推薦不可變的結構來代替類,但就是這樣。

如果有一個好處,立即刪除它們而不是每小時一次,你可以做一些事情,你還可以添加一個計時器,正好是8小時後刪除它,但你已經得到了處理線程安全清理所有計時器等。可能不值得。

我會避免OrderedDictionary方法,因爲它更多的代碼,並且可能會更慢,因爲它必須重新排序每個插入。

這些日子裏常見的口頭禪主要關注保持代碼簡單,只在必要時進行優化。直到你有一個已知的瓶頸並對它進行了描述,你永遠不知道你是否在優化正確的事情。 (從你的描述來看,沒有分辨出哪部分是最慢的)。

+0

OrderedDictionary方法只會在插入時更慢(相對)刪除舊事件時速度要快得多;)。但我同意,如果事件不合適,不值得。 – Cemafor 2013-05-01 16:59:43

相關問題