Java: compare HashMap<String, Object> if value might be an Object[]
I have the following HashMap with properties keys and values:
private HashMap<String, Object> prop_values;
I need to check if one instance of it is equal to another one. In the past, i just did this:
if (prop_values_1.equals(prop_values_2)){
// do something
}
And this worked until i got Object[]
as a value. So, my previous expression always returned false
on such HashMap
with any Object[]
value.
So, i have to implement this method:
private boolean isPropValuesEquals(HashMap<String, Object> pv1, HashMap<String, Object> pv2){
boolean isEquals = true;
if (pv1 == null || pv2 == null){
return false;
}
if (!pv1.keySet().equals(pv2.keySet())){
return false;
}
for (String key : pv1.keySet()){
Object cur_pv1 = pv1.get(key);
Object cur_pv2 = pv2.get(key);
if (cur_pv1 instanceof Object[]){
if (cur_pv2 instanceof Object[]){
isEquals = Arrays.equals((Object[])cur_pv1, (Object[])cur_pv2);
} else {
return false;
}
} else {
isEquals = isEquals && cur_pv1.equals(cur_pv2);
}
if (!isEquals){
return false;
}
}
return isEquals;
}
It works, but it seems to be some kind of hack, and i'm not sure this is the best way to achieve what I need.
So, here's two questions:
why Object[].equals() is not the same as Arrays.equals()? It seems to be painful.
is there some better way to compare HashMap<String, Object>
, if values can be an Object[]
?
The deep problem is that an there's no way to override the equals()
of an array. Why it's not written as "equal elements in the same order" in the first place, I have no idea. It definitely could have been (unless there's some obscure rationale for not doing it; I can't think of any; if you wanted to check for reference equality, you use ==
, so what would a working equals()
harm?).
Your solution is the way to go. Just a couple of details to consider:
Instead of x instanceof Object[]
, you could use x.getClass().isArray()
, so it would work for other arrays as well, such as int[]
(which is not a subclass of Object[]
). Downside: you may have to separately check if x
is null
.
If the arrays may contain nested arrays, consider using Arrays.deepEquals()
.
A demonstration that primitive arrays are not Object[]
s:
Object a = new int[1];
System.out.println("" + (a instanceof Object[])); // false
System.out.println("" + a.getClass().isArray()); // true
Yet another pain in the arse is that even if you find that x
is an array, you still have to handle separately cases for all the different primitive element types. There's no way to handle them in a generic way in Java's type system. Of course, if you don't have primitive arrays in our map, then you don't need to handle this case.
Equality can be different things: is it the same reference (reference equality)? Or does it have the same contents?
The issue with arrays is that they are mutable. equals
and hashCode
of an object must always come as pairs, and the hash code should not change (otherwise objects cannot be found in hash tables). Therefore the normal equals
(and hashCode
) cannot use the arrays content, they have to rely on another (non-mutable) property of the array, which is the reference.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
链接地址: http://www.djcxy.com/p/10700.html