views:

134

answers:

4

I have two instances of the same class. I need to find property(s) which are different amongst them (basically value of the property, say firstName might be different in both). The fields are primitive, complex as well as collections.

Basically, I need to find differences between two instances and if the fields are different in both the instances, I will copy value of the field from first instance to a third instance (diff object).

I think I can use reflection, but the classes are very complex and it might become error prone.

Any help is appreciated.

+1  A: 

write a method like

public YourClass diff(YourClass other) {
    // diff code here
}

or

public static YourClass diff(YourClass first, YourClass second) {
    // diff code here
}

and wrap some unit tests around the implementations.

Reflection might seem more complicated, but it has the following advantages:

1) It can be generic and you can make the same code work with any class
2) It will not have to be changed if the class evolves.

If you want to go with reflection, you can use Class.getDeclaredFields() (google for "java class api 6") to get all the fields on the class, and then you can use the Field api to get the values for an object. If you wanted to be really fancy, you have a static String[] "diffIgnoredFields" and include field names you want to ignore in the diff.

hvgotcodes
-1. This answer doesn't provide any implementation detail for the part that is actually challenging.
Mike Daniels
@mike, how about now?
hvgotcodes
@hvgotcoes, yeah. I undid my downvote. "Diff code here" was not a very good answer to a question about how to write the diff code.
Mike Daniels
@mike yeah, i agree -- i was confused because it seemed like OP wanted to avoid reflection. If he wants to avoid reflection, AFAIK he has limited choices on how to proceed - he has to roll his own.
hvgotcodes
+3  A: 

There is no other way than to use reflection if you want to do it generically. If your fields have getters then you could keep comparing it with equals method. Then you have know the fields at compile time.

fastcodejava
This is a hard problem. Since objects are really pointers in disguise, one needs to be able to distinguish between x.a and x.b pointing to the same object, and x.a and x.b pointing to two different objects, which are equal to each other. By the way, all of the members and members of members must implement `IComparable` properly, or something like that. Also, the diff calculator will have a hard time comparing dictionaries, I think. What makes two dictionaries or sets equal? Do they have to be the same under the hood?
Hamish Grubijan
+3  A: 

Your question is a bit unclear. First you said "two instances of the same class", then you said "the classes are very complex". Is this a generic solution to find differences between instances for any class, or is it just a specific case? The other ambiguity is what you mean by "copy the differences". For example, if its a String, then what is the difference between the two strings that would get copied into the new instance? If its a collection, what is the difference between the collections? What if you have two ArrayLists that have the same things in different orders.

If its a specific case, then you can just create a method on the class where you pass in an instance of the same class. Then you can iterate over each field and compare the differences.

public TheClass difference(TheClass that) {
  TheClass newClass = new TheClas()
  if (this.getName().equals(that.getName()) == false ) {
    newClass.setName(that.getName());
  }
  ...
}

But this can get out of hand depending on how deep your object graph is.

Perhaps the builder pattern might come in handy here if you're trying to build a generic/reusable solution. You might look at the Apache Commons code base and see how they implement HashCodeBuilder and ToStringBuilder. They even have a reflection version of the utilities. See how they handle deep and shallow equals.

Javid Jamae
*"But this can get out of hand depending on how deep your object graph is"* ... and it gets even more complex if the graph in not tree structured.
Stephen C
A: 

You need to be careful. Some formulations of this problem are essentially the same as the Subgraph Isomorphism Problem which is known to be NP complete.

Stephen C