【问题标题】:HashMap with date ranges具有日期范围的 HashMap
【发布时间】:2013-03-12 21:53:54
【问题描述】:

我需要根据多键非常快找到一些值。 密钥由以下部分组成: < Int userId, String measureName, Date startDate, Date endDate > 并且值是双精度的。

问题是我必须要求指示一天的值,而不是日期范围。 因此,如果我要求userIdmeasureName 和一天,则数据结构必须以日期在 startDateendDate 之间的值作为答案(日期范围之间没有重叠) .

我不明白哪个是更好的数据结构来实现这一点。哈希表?树图?多键映射?范围地图?帮助! :)

【问题讨论】:

  • 每个用户/度量组合可能有多少条目?
  • 如果您考虑智能计量/时间序列,则没有。寻找其他解决方案。类似于时间序列
  • 不要太多,比如说100,问题是问了很多时间。 (经常调用的函数需要 80k 次)
  • 日期范围有多大?也许只需为范围内的每个日期创建一个条目。这是旧的内存与速度决定。
  • Guava 的RangeMap ?

标签: java data-structures hashmap


【解决方案1】:

我认为您应该使用 TreeMap 和以下方法: http://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html#floorEntry(K) http://docs.oracle.com/javase/6/docs/api/java/util/TreeMap.html#higherEntry(K) 但在比较函数中仅使用一个日期 - startDate 或 endDate。由于这些范围不重叠,这应该不是问题,并且可以使用 TreeMap 中提到的方法。

例如:如果您决定使用endDate(以及除其他日期以外的其他字段)进行比较,则应使用方法floorEntry

【讨论】:

  • 虽然没有重叠,但可能有些日期不在开始/结束日期范围内...
  • ... 但是你应该只需要比较 endDate 一次。
  • @jahroy 哦,我明白了;我误解并认为建议是直接使用日期作为地图键。
【解决方案2】:

带有自定义键对象的 TreeMap 是最好的。你会有类似的东西:

...
TreeMap<MyMultiKey,Double> map = ...

class MyMultiKey implements Comparable<MyMultiKey>{
...
}

假设 MyMultiKeycompareTo 方法已实现以正确排序您的多键,您可以在每次想要使用 map.floorKey(MyMultiKey m) 和 @987654326 搜索特定日期时创建一个新的 MyMultiKey 实例@ 以确保您找到的密钥的开始和结束时间包含您在新密钥实例中指定的日期。

【讨论】:

    【解决方案3】:

    我推荐一些 Map 作为 User/Measurement 部分键。 该值将是一个排序的元组数组(日期范围,floatval)。 在此数组中,您对包含日期的日期范围执行二进制搜索。

    【讨论】:

      【解决方案4】:

      Map 和订购的List 的组合怎么样?该地图有userIdmeasureName的复合键,值是日期范围的排序列表和双value

      Map<Key,List<Entry>> data = new HashMap<>();
      List<Entry> entries = data.get(new Key(userId, measureName));
      int i = Collections.binarySearch(entries, new Entry(searchDate,searchDate, 0.0));
      double value = i < 0 ? 0.0 : entries.get(i).value;
      

      Key 必须使用其成员 userIdmeasureName 来实现 hashCode()equals()Entry 必须实现 Comparable&lt;Entry&gt; 其中 compareTo() 必须返回 0 如果一个范围是另一个范围的一部分(startDate 比较是 = 0 或 0 如果 startDate 比较是 >= 0 和 endDate比较是 value。

      如果您主要阅读而不修改此结构,它应该很快。如果使用较多,比较将被编译为本机。如果该功能仅适用于单个用户并且仅测量,则可以仅使用排序列表,如果仅适用于单个用户,则可以创建 Map&lt;UserId&lt;Map&lt;MeasureName,List&lt;Entry&gt;&gt;&gt;&gt; 类似的结构。

      先尝试一个简单的解决方案,前后测量,仅在需要时进行性能优化。

      【讨论】:

        猜你喜欢
        • 2020-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-07
        • 2014-06-15
        • 2019-12-12
        相关资源
        最近更新 更多