我想检查 2 之间的相等性HashMap<Number,String>
。我的想法是将每个 Number 转换为 BigDecimal withnew BigDecimal(number.toString())
然后检查相等性,而不是比较 2 Maps 时使用compareTo() == 0
的基本值。equals
谁有一个很好的实现,甚至更好:一个更好的想法?
我想检查 2 之间的相等性HashMap<Number,String>
。我的想法是将每个 Number 转换为 BigDecimal withnew BigDecimal(number.toString())
然后检查相等性,而不是比较 2 Maps 时使用compareTo() == 0
的基本值。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()
只需要复制一个,如果它们的大小不同,则避免任何复制,并检测键冲突。