(original) (raw)
Hi,
Some suggestions:
1) Any equals*(a, b) methods should support a==null && b==null returning true, only a==null returning -1, and only b==null returning +1. This is very useful for much the same reasons that it's useful in SQL (although the exact ordering of null/non-null is debatable - SQL defaults to "nulls last" but allows you to specify NULLS FIRST, and I agree that its default "nulls first" makes more sense most of the time). This handling of nulls should also extend to any elements of a and b.
2) What the platform REALLY needs is a System.arrayequals(Object src1, int pos1, Object src2, int pos2, int length) that, just like the existing arraycopy(), handles arrays of arbitrary types (that's why src1/src2 are specified as Object). The implementation is trivial (with JNI): just compare the element types, do all the parameter/bound checking and if OK, call memcmp() with the addresses of src1[pos1] and src2[pos2], and length translated to bytes. A better implementation would perform intrinsic compilation. I think the various typed Arrays.equals(a,b) methods already do such optimization (the reason for documentation like: "Unlike the == operator, this method considers
NaN equals to itself, and 0.0d unequal to -0.0d."), but these still leave use with the cost of a long case analysis for scenarios like deepEquals() that must handle arrays of arbitrary element-types. IMHO all those typed equals(a,b) should just delegate to a single method, in the System class (not Arrays, not ObjectUtils or whatever), that provides a low-level "raw equals" function. With this low-level (but still safe) function, we can build higher-level APIs like a deepEquals(a,b) with optimum performance. Also, in the current platform there's ByteBuffer.equals() that supports comparison of buffers of arbitrary element types without case analysis, and I guess is also compiled as intrinsic; but I don't want to wrap all my arrays in NIO buffers. The ByteBuffer.equals() should also delegate to the unified System.arrayequals().
A+
Osvaldo
Another piece of functionality requested in the j.u.Objects thread was a deepEquals(Object a, Object b.) method that "did the right thing" if the arguments happened to dynamically be arrays.
I've been thinking a bit how this might be implemented.
The array-ness of a and b would need to be determined, after any up-front null-checks
boolean aIsArray = a.getClass().isArray();
boolean bIsArray = b.getClass().isArray();
followed various case-analyses.
if (aIsArray && bIsArray) {
� �Class aComponentType = a.getClass().getComponentType();
� �Class bComponentType = b.getClass().getComponentType();
� if (aComponentType == bComponentType) {
� � � // long case analysis to cast and call Arrays.deepEquals if ComponentType is a reference type
� � � // or the matching Arrays.equals(primitiveComponent[], primitiveComponent[]) method if
� � � // aComponentType.isPrimitive().
� } else
� � � return false;
} else
� return a.equals(b);
Certainly a bit messy internally.
What are scenarios where this method would be used?
-Joe