j.u.Objects follow-up: deepEquals(Object, Object)?

Osvaldo Doederlein opinali at gmail.com
Fri Oct 9 12:50:23 UTC 2009


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().


2009/10/8 Joseph D. Darcy <Joe.Darcy at 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/core-libs-dev/attachments/20091009/0bb5265a/attachment.html>

More information about the core-libs-dev mailing list