Wednesday, January 09, 2008

Experience using apache commons EqualsBuilder class

Following are my learnings on how to use the EqualsBuilder class in apache commons lang library.

C:\Work\EqualsProto\src\equalsproto\Main.java


package equalsproto;

//~--- non-JDK imports --------------------------------------------------------

import java.util.Arrays;
import org.apache.commons.lang.builder.EqualsBuilder;


class A
{
private String s = "Watsh";
private int x = 10;
private float y = 20.2f;

//~--- constructors --------------------------------------------------------

A() {}

A(int i, int i0, String string)
{
this.x = i;
this.y = i0;
this.s = string;
}

//~--- methods -------------------------------------------------------------

/**
* Method description
*
*
* @param obj

*
* @return
*/
@Override
public boolean equals(Object obj)
{
if (obj instanceof A == false) {
return false;
}

if (this == obj) {
return true;
}

A rhs = (A) obj;

/** Note:

* Do not use appendSuper when the super class is java.lang.Object as

* default implementation of equals in Object class will return true only

* when two references are pointing to the same object instance and hence

* the effect is not desirable.
*/
return new EqualsBuilder().append(s, rhs.s).append(x,
rhs.x).append(y, rhs.y).isEquals();
}
}



class B
{
private String z = "Rajneesh";
private A a;
private A[] array;

//~--- constructors --------------------------------------------------------

B(String z, A a, A[] array)
{
this.z = z;
this.a = a;
this.array = array;
}

@Override
/**
* Learning:
* 1. appendSuper() should not be used as it then calls super.equals()

* for java.lang.Object class which will return true only when both lhs and

* rhs references point to the same object instance and hence will return false

* when the 2 object instances are different but meaningfully equivalent.

*
* 2. To compare arrays, you will either need to use the

* EqualsBuilder.reflectionEquals() approach or if you are using the

* EqualsBuilder.append() approach then append(array1, array2) calls

* array1.equals(array2) which will only do a shallow comparison for the

* 2 arrays involved. So in such a case, you must use Arrays.deepEquals() for

* all array members of your class and once that equality is met you can use

* EqualsBuilder.append() for rest of the non-array instances.

*
* NOTE: I have not tested for how this approach works for Collection classes.

*/
/*public boolean equals(Object obj)
{
if (obj instanceof A == false) {
return false;
}

if (this == obj) {
return true;
}

B rhs = (B) obj;

return new EqualsBuilder().append(z, rhs.z).append(a,

rhs.a).append(array, rhs.array).isEquals();
}*/
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}
}



/** Testing the use of EqualsBuilder.
*
* @author wrajnees

*/
public class Main
{

/**
* @param args the command line arguments

*/
public static void main(String[] args)
{
A a1 = new A(2, 43, "xxx");
A a2 = new A(2, 43, "xxx");
if (a1.equals(a2)) {
p("a1 equals a2");
} else {
p("a1 not equals a2");
}

A[] array1 = new A[2];
A[] array2 = new A[2];

array1[0] = a1;
array1[1] = new A();

array2[0] = a2;
array2[1] = new A();

// comparing arrays

if (Arrays.deepEquals(array1, array2)) {
//if (array1.equals(a2)) { // -- does not work
p("arrays are equal");
} else {
p("arrays arent equal");
}

// comparing more complex object with containment and array

B b1 = new B("Test", a1, array1);
B b2 = new B("Test", a2, array2);
if (b1.equals(b2)) {
p("b1 equals b2");
} else {
p("b1 not equals b2");
}
}

private static void p(String s) {
System.out.println(s);
}
}



1 comment:

Neill Laney said...

My commons-lang EqualsBuilder didn't work until I overrode and implemented HashBuilder.toHashCode. Don't know if that was assumed knowledge, but thanks for the post!

Book notes: Designing Data-Intensive Applications: The Big Ideas Behind Reliable, Scalable, and Maintainable Systems, by Martin Kleppmann

My notes from the excellent book on how software has evolved to handle data from hierarchical databases to the NoSQL -  https://www.goodrea...