【问题标题】:Find The Closest Answer in HashMap在 HashMap 中找到最接近的答案
【发布时间】:2012-02-28 13:42:21
【问题描述】:

我想在 hashmap 中搜索一个键并找到离该键最近的一个!

    HashMap<Long, Object> map = new HashMap<Long , Object>();

所以基本上我想搜索一个 long,如果它在地图中不存在,则找到与该 long 值最接近的匹配项! 我该怎么做!?

提前感谢

【问题讨论】:

  • 有趣的是,您的问题表明您有一个 HashMap(您没有问哪种地图类型最适合使用,您说您使用的是 HaspMap),但您选择的答案使用TreeMap。将一个转换为另一个涉及迭代(在map.putAll() 内),因此您选择了最慢的实现,并且它使用的代码不比我的答案少。我相信我的答案会胜过公认的答案。

标签: java hashmap


【解决方案1】:

如果不迭代其所有键,您将无法使用 HashMap 执行此操作。我认为这不是您所追求的,所以这是一种使用TreeMap 的方法:

TreeMap<Long,Object> map = new TreeMap<Long,Object>();
Long key = 42;
Map.Entry<Long,Object> low = map.floorEntry(key);
Map.Entry<Long,Object> high = map.ceilingEntry(key);
Object res = null;
if (low != null && high != null) {
    res = Math.abs(key-low.getKey()) < Math.abs(key-high.getKey())
    ?   low.getValue()
    :   high.getValue();
} else if (low != null || high != null) {
    res = low != null ? low.getValue() : high.getValue();
}

【讨论】:

  • 非常感谢!还有一件事是这个树形图快吗?比较地图?并与数组列表进行比较? (我知道它们比 arraylist 快,但只是为了确定):D
  • @KhashayarNapster 树映射相当快,但通常不如哈希映射快。它们随着键数的增加而减慢,但减慢相对较小(它是对数的)。例如,如果树图 A 具有 1,000 条目,而树图 B 具有 1,000,000 条目,则搜索 B 的速度仅是搜索 A 的两倍。
【解决方案2】:

使用像 TreeMap 这样的 NavigableMap

long key = 
NavigableMap<Long, Object> map = new TreeMap<Long , Object>();

Long before = map.floorKey(key);
Long after = map.ceilingKey(key);
if (before == null) return after;
if (after == null) return before;
return (key - before < after - key 
       || after - key < 0) 
       && key - before > 0 ? before : after;

【讨论】:

  • key - before 翻转的边缘情况呢?键可能是散列,所以它可能会发生。即便如此,+1!
  • 哈希被设计为伪随机且不可预测的顺序,但你是对的,可能存在溢出。
【解决方案3】:

遍历所有键以找到与目标键差异最小的键。

这里有一些代码可以做到这一点:

public static Long nearestKey(Map<Long, Object> map, Long target) {
    double minDiff = Double.MAX_VALUE;
    Long nearest = null;
    for (long key : map.keySet()) {
        double diff = Math.abs((double) target - (double) key);
        if (diff < minDiff) {
            nearest = key;
            minDiff = diff;
        }
    }
    return nearest;
}

所有转换为double 的目的都是为了防止在目标为大负数且映射键为大正数时发生翻转

【讨论】:

  • 这似乎回答了原始问题,以获得最近的键(不是值)。我不清楚其他一些答案在做什么。
【解决方案4】:

解决办法:

  1. 如果您按排序顺序将值插入到 hashMap 中,您可以使用 LinkedHashMap 以便维护插入顺序。

  2. 现在我们可以对键执行二进制搜索,而不是遍历所有键(就像在其他一些答案中一样)。

  3. 如果对所有键的迭代进行 n 次比较,则二进制搜索将采用 log(n) 并以 2 为基数进行比较。

这里要注意的一点是,这仅在地图已排序时才有效。

差异图比较:

  • 哈希映射作为通用映射实现很好,它 提供快速的存储和检索操作。然而,它跌 短,因为它的条目排列混乱无序。

    这会导致它在存在大量 迭代,因为底层数组的整个容量会影响 除了条目数之外的遍历。

  • 链接的哈希映射具有哈希映射的良好属性,并添加 对条目进行排序。它在有很多的地方表现更好 迭代,因为只考虑条目的数量 无论容量大小。
  • 树形图通过提供完整的 控制键的排序方式。另一方面,它 提供比其他两种替代方案更差的总体性能。

我们可以说链接哈希图减少了哈希图排序中的混乱,而不会导致树状图的性能损失。

【讨论】:

    【解决方案5】:

    哈希(包括 HashMap)没有排序(实现 'Comparable'),它们仅适用于 equals() 和 hashCode() 的实现。

    换句话说,它是做不到的。您可以尝试使用有序列表或集合。

    【讨论】:

      【解决方案6】:

      不是吗?这不是 get 函数应该如何工作的方式。 我猜您可能可以使用 TreeMap 并使用 getHeadMap/getTailMap 并使用一些逻辑来找到最接近的匹配项。但这可能需要摆弄一下。 毕竟最接近意味着什么? ...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-26
        • 2017-08-28
        • 1970-01-01
        • 2016-11-21
        • 2012-05-15
        • 1970-01-01
        • 2019-08-17
        • 2015-03-01
        相关资源
        最近更新 更多