Java - Get Differences Between Two Objects

This tutorial shows you how to get the list of properties with different value on two objects.

Imagine you have two instances of a Class and you want to find what properties have different value. If the Class only has a few properties, you can write the code by comparing each property. But, if the Class has so many properties, the code will be very long and you'll need to update the method used for comparing objects. In addition, you may forget to update the method when you add a new property.

Actually it can be done using Reflection API. But, if you're looking for a simple solution without accessing the Reflection API, there is a library called java-object-diff. It can be used to get the differences between two objects even if the class is nested.

For example, we have Item class whose one of the properties is of type Category class.

Item.java

  package com.woolha.model;
  
  import java.util.Date;
  
  import lombok.*;
  
  @NoArgsConstructor
  @Getter
  @Setter
  public class Item {
  
      private String name;
  
      private int quantity;
  
      private Category category;
  
      private Date updatedAt;
  }

Category.java

  package com.woolha.model;
  
  import lombok.Getter;
  import lombok.NoArgsConstructor;
  import lombok.Setter;
  
  @NoArgsConstructor
  @Getter
  @Setter
  public class Category {
  
      private String name;
  
      private String description;
  }

And here's an example how to get the differences with java-object-diff.

  final Category category1 = new Category();
  category1.setName("Cat1");
  category1.setName("The first category");
  
  final Category category2 = new Category();
  category2.setName("Cat2");
  category2.setName("The second category");
  
  final Item item1 = new Item();
  item1.setName("A");
  item1.setQuantity(1);
  item1.setUpdatedAt(new Date());
  item1.setCategory(category1);
  
  final Item item2 = new Item();
  item2.setName("B");
  item2.setQuantity(1);
  item2.setUpdatedAt(new Date());
  item2.setCategory(category2);
  
  DiffNode diff = ObjectDifferBuilder.buildDefault().compare(item1, item2);
  
  if (diff.hasChanges()) {
      diff.visit(new DiffNode.Visitor() {
          public void node(DiffNode node, Visit visit)
          {
              if (!node.hasChildren()) { // Only print if the property has no child
                  final Object oldValue = node.canonicalGet(item1);
                  final Object newValue = node.canonicalGet(item2);

                  final String message = node.getPropertyName() + " changed from " +
                          oldValue + " to " + newValue;
                  System.out.println(message);
              }
          }
      });
  } else {
      System.out.println("No differences");
  }

The library works by listing which paths have difference. It stores the paths in a tree structure, each node representing a path whose value is not equal on both objects. Those nodes can be visited in DFS (Deep First Search) way.

In the example above, the paths are / (the root path), /category (object), /category/name, /category/description and /name. If you want to ignore paths that represent an Object, you can filter it by using !node.hasChildren().