如何检查2 HashMap <number,string =“”>?</number,>之间的相等性

时间:2013-04-30 15:23:42

标签: java map bigdecimal comparable

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

谁有一个很好的实现,甚至更好:一个更好的主意?

1 个答案:

答案 0 :(得分:0)

这看起来很像X-Y problem;正如评论中指出的那样,比较任意Number个对象并没有多大意义;为什么不直接制作地图Map<BigDecimal, String>,并且只在必要时直接使用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<BigDecimal, V>并调用.equals(),但这需要复制两张地图,而numberMapEquality()只需要复制一张,如果他们需要复制则避免任何复制大小不一样,并检测到关键碰撞。