【问题标题】:How to check equality between 2 HashMap<Number, String>?如何检查 2 HashMap<Number, String> 之间的相等性?
【发布时间】:2013-04-24 14:02:41
【问题描述】:

我想检查 2 个HashMap&lt;Number,String&gt; 之间的相等性。 我的想法是使用 new BigDecimal(number.toString()) 将每个 Number 转换为 BigDecimal,然后使用 compareTo() == 0 而不是比较 2 个地图时使用的基本 equals 检查相等性。

谁有一个很好的实现,甚至更好:一个更好的想法?

【问题讨论】:

  • 这取决于您如何定义两个映射是否等于。它们是否应该只有相同的键、相同的值、相同的键值对?
  • 在我的例子中是相同的键值对。
  • 1:你不能在数字之间做相等。 2 :你应该知道永远不要在 2 BigDecimal 之间做等于,因为它是基于比例的
  • @Shark - 这是一个 Java 问题。 Java 中没有 memcmp 这样的东西!
  • @Olivier:您必须将两张地图之间的“相等”定义形式化。如果 map 1 包含映射 [int 42 -> "foo"] 和 [long 42 -> "bar"] 并且 map 2 包含映射 [int 42 -> "bar"] 和 [long 42 -> "map" ]。地图是平等的吗?还有很多其他的极端情况,既不明显,也不在您的描述中指定。

标签: java map bigdecimal comparable


【解决方案1】:

这看起来很像X-Y problem;正如 cmets 中所指出的,比较任意 Number 对象没有多大意义;为什么不直接制作您的地图Map&lt;BigDecimal, String&gt; 并始终直接使用BigDecimal(如有必要,normalizedstripTrailingZeros() 一起使用)?然后你可以使用标准的Map 相等。考虑退后一步,首先询问您是否真的需要您所描述的行为。

值得注意的是,Number 没有实现 Comparable,这应该是一个非常明确的提示,您不应该尝试比较任意的 Number 实例。


如果由于某种原因这不是一个选项,这里是您描述的行为的合理实现。

private static BigDecimal toBigDecimal(Number n) {
  return n instanceof BigDecimal ? (BigDecimal)n : new BigDecimal(n.toString());
}

public static <V> boolean numberMapEquality(
    Map<Number, ? extends V> a, Map<Number, ? extends V> b) {
  if (a == b) return true;
  if (a.size() != b.size()) return false;

  // TreeMap uses .compareTo(), not .equals()
  TreeMap<BigDecimal, V> bdMap = new TreeMap<>();
  for (Entry<Number, ? extends V> e : a.entrySet()) {
    bdMap.put(toBigDecimal(e.getKey()), e.getValue());
  }

  if (bdMap.size() != a.size()) {
    // comment out if you don't care about this edge-case - but you should
    throw new IllegalArgumentException(
        "Multiple keys in 'a' normalize to the same value; " +
        "equality comparison is unsafe.");
  }

  // Taken from AbstractMap.equals()
  for (Entry<Number, ? extends V> e : b.entrySet()) {
    BigDecimal bdKey = toBigDecimal(e.getKey());
    V value = e.getValue();
    if (value == null) {
      if (!(bdMap.get(bdKey)==null && bdMap.containsKey(bdKey)))
        return false;
    } else {
      if (!value.equals(bdMap.get(bdKey)))
        return false;
    }
  }
  return true;
}

或者,只需将两个映射复制到TreeMap&lt;BigDecimal, V&gt; 并调用.equals(),但这需要复制两个映射,而numberMapEquality() 只需要复制一个,如果它们的大小不同,则避免任何复制,并检测密钥碰撞。

【讨论】:

    猜你喜欢
    • 2011-05-04
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 2018-07-04
    相关资源
    最近更新 更多