具有datetime +字符串键的目录,以及自动删除旧条目

时间:2013-05-01 16:13:58

标签: c# linq collections

我有一个应用程序接收某些“事件”,由12个字符串和一个DateTime唯一标识。在每个事件处关联一个字符串的结果。 我需要将这些事件保存在内存中(例如最多8小时)并且能够,如果我第二次收到相同的事件,能够知道我已经收到它(在过去的8小时内) 。 存储的事件将少于1000。 我不能使用外部存储器,它必须在内存中完成。

我的想法是使用一个字典,其中键是一个由字符串和日期时间组成的类,该值是结果。

编辑:字符串本身(实际上是MAC地址)不能唯一地标识事件,它是MAC和日期时间,这两者组合是唯一的,这就是密钥必须由两者组成的原因。 应用程序是从客户端接收特定事件的服务器:客户端MAC和客户端日期时间(不能使用guid)在客户端上标记事件。 可能会发生客户端重新传输相同的数据,并通过检查字典中的MAC / Datetime密钥,我知道我已经收到了该数据。

然后,每小时(例如),我可以预览整个集合并删除日期时间超过8小时的所有密钥。

您能否建议更好地解决问题或我选择的数据格式?在代码的性能和清洁方面。 或者更好的方法来删除旧数据,例如LINQ。

谢谢, 马蒂亚

4 个答案:

答案 0 :(得分:1)

活动时间必须成为密钥的一部分 - 如果是,您如何能够告诉您已经收到此活动?因此,您应该移动到一个字典,其中键是事件名称,值是日期和结果的元组。

偶尔你可以使用LINQ轻松修剪字典中的旧数据:

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

答案 1 :(得分:1)

如果要求声明每小时更新一次就足够了,并且字典中的项目从未超过1000个,那么您的解决方案应该是完全足够的,并且可能是其他任何查看您的代码的人最容易理解的。我可能会为键而不是类推荐不可变的结构,但就是这样。

如果立即删除而不是每小时一次有好处,你可以做一些事情,你也可以添加一个定时器,在8小时后删除它,但是你必须处理有线程安全和清理所有计时器等。可能不值得。

我会避免使用OrderedDictionary方法,因为它的代码更多,并且可能更慢,因为它必须为每个插入重新排序。

现在最常关注保持代码简单,只在必要时进行优化是一种常见的口头禅。在你有一个已知的瓶颈并对其进行分析之前,你永远不知道你是否正在优化正确的东西。 (根据你的描述,没有说明哪一部分在没有剖析的情况下会最慢)。

答案 2 :(得分:0)

我会使用OrderedDictionary,其中键是12个字符标识符,结果和日期时间是值的一部分。遗憾的是OrderedDictionary不是通用的(键和值是对象),因此您需要自己进行转换和类型检查。当您需要删除旧事件时,您可以通过OrderedDictionary进行操作,并在获得足够新的时间时停止。这假定您将它们添加到字典时按顺序使用的日期时间。

答案 3 :(得分:0)

我会去一本字典。

通过这种方式,您可以非常快速地搜索字符串(O(1) - 操作)。

其他收藏品较慢:

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