繁体   English   中英

如何检查2 HashMap之间的相等性 <Number, String> ?

[英]How to check equality between 2 HashMap<Number, String>?

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

谁能很好地实现这一目标,甚至更好:更好的主意?

这看起来很像XY问题 ; 如评论中所指出的,比较任意Number对象没有多大意义; 为什么不只让您的地图Map<BigDecimal, String>并始终直接直接使用BigDecimal (必要时使用stripTrailingZeros() 标准化 )? 然后,您可以使用标准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<BigDecimal, V>并调用.equals() ,但这需要复制两个地图,而numberMapEquality()只需要复制一个,避免大小不相同的任何复制,并检测按键碰撞。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM