(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

2009/10/8 Joseph D. Darcy <Joe.Darcy@sun.com>

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