简体   繁体   中英

Comparison of two objects without oids at all levels

I have such objcects:

import lombok.Builder;
import lombok.Data;

import java.util.List;

@Data
@Builder
public class Grandfather {
    private Integer oid;
    private String name;
    private List<Father> childs;
}

@Data
@Builder
public class Father {
    private Integer oid;
    private String name;
    private List<Son> childs;
}

@Data
@Builder
public class Son {
    private Integer oid;
    private String name;
}

I would like to compare two objects which are type of Grandfather by recursion method, that use also reflection. That method compare all fields of object at all level without field oid. Below I present the objects that should be treated as the same when compared:

Son son1 = Son.builder()
                .oid(100)
                .name("Paul")
                .build();
        Son son2 = Son.builder()
                .oid(null)
                .name("Paul")
                .build();
        Father father1 = Father.builder()
                .oid(32)
                .name("Alex")
                .childs(Collections.singletonList(son1))
                .build();
        Father father2 = Father.builder()
                .oid(567)
                .name("Alex")
                .childs(Collections.singletonList(son2))
                .build();
        Grandfather grandfather1 = Grandfather.builder()
                .oid(12)
                .name("John")
                .childs(Collections.singletonList(father1))
                .build();
        Grandfather grandfather2 = Grandfather.builder()
                .oid(1222)
                .name("John")
                .childs(Collections.singletonList(father2))
                .build();

I wrote this method but unfortunately it does not work. This method uses reflection through which it iterates through the objects (fields) of a given object. Unfortunately, it uses recursions badly.

public static boolean haveSameValuesExceptOneField(Class<?> type, Object t1, Object t2, String exceptGetter)
            throws Exception {
        for (Method m : type.getMethods()) {
            if (!m.getName().equals(exceptGetter) && isGetter(m)) {
                final Object o1 = m.invoke(t1);
                final Object o2 = m.invoke(t2);
                if (!Objects.equals(o1, o2)) {
                    return haveSameValuesExceptOneField(m.invoke(t2).getClass(), m.invoke(t1), m.invoke(t2), exceptGetter);
                }
            }
        }
        return true;
    }

private static boolean isGetter(Method method) {
        return method.getName().startsWith("get") && method.getParameterTypes().length == 0;
    }

This is how I call this method:

System.out.println(haveSameValuesExceptOneField(Grandfather.class, grandfather1, grandfather2, "getOid"));

How can I fix this method to make it work the way I want?

In your for (Method m: type.getMethods()) loop you return after the comparison of the first pair of fields which are not Objects.equal to each other. The first field such that t1.getField() is not Objects.equal to t2.getField() will stop the comparison of other fields in objects t1 and t2.

if (!Objects.equals(o1, o2) &&
    !haveSameValuesExceptOneField(m.invoke(t2).getClass(), 
                                  m.invoke(t1), 
                                  m.invoke(t2), 
                                  exceptGetter)) {
        return false;
    }
}
// continue the loop - keep comparing other fields

If any of you know how to compare these objects, not necessarily with the use of reflection or recursion, then I am asking for such solutions as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM