[ACCEPTED]-how to generically compare entire java beans?-javabeans

Accepted answer
Score: 23

Try EqualsBuilder.reflectionEquals() of commons-lang. EqualsBuilder has a set of methods 4 to include all fields, all non-transient 3 fields and all but certain fields.

If all 2 else fails, the code could serve as a good 1 example how to implement this.

Score: 8

To answer your question directly, you could 19 use reflection to do equality checking of 18 beans. There are a few snags you need to 17 be aware of.

There are rules regarding the 16 behaviour of equals() and hashcode(). These 15 rules talk about symmetry, consitency and 14 reflexiveness which may be hard to do when 13 your equals method behaves dynamically based 12 on the other object you're passing in.

Interesting 11 read: http://www.geocities.com/technofundo/tech/java/equalhash.html

Generally speaking, I think you are 10 better off creating your own hashcode and 9 equals methods. There are a fwe good plugins 8 which can automatically generate that code 7 for you based on the class properties.

Having 6 said all this, here are some (old style) methods 5 for getting getters, setters and properties 4 I wrote a long time ago:

private Map getPrivateFields(Class clazz, Map getters, Map setters) {
    Field[] fields = clazz.getDeclaredFields();
    Map m = new HashMap();
    for (int i = 0; i < fields.length; i++) {
        int modifiers = fields[i].getModifiers();
        if (Modifier.isPrivate(modifiers) && !Modifier.isStatic(modifiers) && !Modifier.isFinal(modifiers)) {
            String propName = fields[i].getName();
            if (getters.get(propName) != null && setters.get(propName) != null) {
                m.put(fields[i].getName(), fields[i]);
            }
        }
    }
    return m;
}

The Getters:

private Map getGetters(Class clazz) {
    Method[] methods = clazz.getMethods();
    Map m = new HashMap();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().startsWith("get")) {
            int modifiers = methods[i].getModifiers();
            if (validAccessMethod(modifiers)) {
                m.put(getPropertyName(methods[i].getName()), methods[i]);
            }
        }
    }
    return m;
}

And 3 the Setters:

private Map getSetters(Class clazz, Map getters) {
    Method[] methods = clazz.getMethods();
    Map m = new HashMap();
    for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().startsWith("set")) {
            int modifiers = methods[i].getModifiers();
            String propName = getPropertyName(methods[i].getName());
            Method getter = (Method) getters.get(propName);

            if (validAccessMethod(modifiers) && getter != null) {
                Class returnType = getter.getReturnType();
                Class setType = methods[i].getParameterTypes()[0];
                int numTypes = methods[i].getParameterTypes().length;

                if (returnType.equals(setType) && numTypes == 1) {
                    m.put(propName, methods[i]);
                }
            }
        }
    }
    return m;
}

Maybe you can use this to roll 2 your own.

Edit: Ofcourse the reflectionbuilder in Aaron Digulla's answer is much better 1 than my handywork.

Score: 2

As mentioned above, a reflection-based implementation 8 will do what you want. I just wanted to 7 warn you, that reflection is quite costly 6 and such an implementation could be comparably 5 slow. If you just need to do occasional 4 comparisons, you will be fine. However, if 3 you have huge datasets and frequent equality 2 checks (e.g. filtering of big tables) you 1 might get into trouble.

Score: 0

Or, although not a direct answer to your 11 question, but it might be an answer to your 10 problem (i.e. remove the effort of doing 9 boilerplate code while being super fast)

if you 8 use Eclipse, the following steps will auto 7 generate the hashCode and equals for you:

Source 6 > Generate hashCode and equals...

and then 5 select the fields, it's super effective! :D

Cheers 4 and I hope it helps whoever comes here with 3 the purpose of cutting some time writing 2 boilerplate.

PS: I'm sure other popular IDEs 1 must have similar features.

More Related questions