1

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

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

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

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

你能建议一个更好的方法来解决这个问题或我选择的数据格式吗?在代码的性能和清洁度方面。或者是删除旧数据的更好方法,例如使用 LINQ。

谢谢, 马蒂亚

4

4 回答 4

3

事件时间必须不是关键的一部分——如果是,你怎么知道你已经收到了这个事件?因此,您应该转到一个字典,其中键是事件名称,值是日期和结果的元组。

偶尔,您可以使用 LINQ 轻松地从字典中删除旧数据:

dictionary = dictionary
    .Where(p => p.Value.DateOfEvent >= DateTime.Now.AddHours(-8))
    .ToDictionary();
于 2013-05-01T16:30:09.740 回答
1

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

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

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

这些天来,首先关注保持代码简单,只在必要时进行优化是一个普遍的口头禅。除非你有一个已知的瓶颈并对其进行分析,否则你永远不知道你是否优化了正确的东西。(根据您的描述,如果不对其进行分析,则无法确定哪个部分最慢)。

于 2013-05-01T16:33:27.643 回答
0

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

于 2013-05-01T16:24:27.627 回答
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;
    }
}
于 2013-05-01T17:11:07.043 回答