我想检查2 HashMap<Number,String>
之间的平等。
我的想法是使用new BigDecimal(number.toString())
将每个数字转换为BigDecimal,然后使用compareTo() == 0
检查相等性,而不是比较2个地图时使用的基本equals
。
谁有一个很好的实现,甚至更好:一个更好的主意?
答案 0 :(得分:0)
这看起来很像X-Y problem;正如评论中指出的那样,比较任意Number
个对象并没有多大意义;为什么不直接制作地图Map<BigDecimal, String>
,并且只在必要时直接使用BigDecimal
normalized和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()
只需要复制一张,如果他们需要复制则避免任何复制大小不一样,并检测到关键碰撞。