With Java 8:

Comparator.comparing((Person p)->p.firstName)
          .thenComparing(p->p.lastName)
          .thenComparingInt(p->p.age);

If you have accessor methods:

Comparator.comparing(Person::getFirstName)
          .thenComparing(Person::getLastName)
          .thenComparingInt(Person::getAge);

If a class implements Comparable then such comparator may be used in compareTo method:

@Override
public int compareTo(Person o){
    return Comparator.comparing(Person::getFirstName)
              .thenComparing(Person::getLastName)
              .thenComparingInt(Person::getAge)
              .compare(this, o);
}
🌐
Baeldung
baeldung.com › home › java › core java › comparing objects in java
Comparing Objects in Java | Baeldung
October 10, 2025 - As usual, it returns an integer that may be negative, zero, or positive if the first argument is lesser, equal, or greater than the second, respectively. Similar methods exist for all the primitive types, except for bytes. Finally, the Guava library offers the ComparisonChain class that allows us to compare two objects through a chain of comparisons.
Discussions

[JUnits] How to compare 2 complex objects without overriding toequals/hashcode methods?
Serialize both to JSON with Gson and pretty printing turned on. Now just compare the strings and get a nice human-readable output. More on reddit.com
🌐 r/java
17
4
February 7, 2015
Java CompareTo Sorting - Sorting Multiple Fields for Same Object
I have an ArrayList of objects - Player, and I currently have the code to sort by its field, last name. Player has an additional field, height, which I need to sort by in other areas of the application. I believe I understand that overriding the compareTo gives the information to the sort method of field it's sorting on. Since I need to sort with two ... More on teamtreehouse.com
🌐 teamtreehouse.com
1
September 14, 2017
How to recursively compare two objects with different field names but same values
I want to compare two objects (DTO and an Entity) using AssertJ's recursive comparison, for purpose of unit-testing DTO->Entity mapper. Both of these objects have fields with pretty much the same v... More on github.com
🌐 github.com
4
September 23, 2021
java - How to compare two objects and get the changed fields - Stack Overflow
In here im logging the changes that has been done to a particular Object record. So im comparing the old record and the updated record to log the updated fields as a String. Any idea how can I do t... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 5
3

The “different member variables” is irrelevant. It’s an implementation detail. What you need is a set of rules which of two people comes first.

You could for example sort by family name, then given name, then date of birth, and if these are all three equal, take the name of the school, university or company (which will be different member variables) and compare them as strings. If that is equal, you might have student and employee ids, and the student ids might be unique, and the employee ids might be unique, but student and employee ids might be the same. So you could sort then students first ordered by id, followed by employees sorted by id, if you might sort by if first if student and employee ids are comparable.

(University or school and employer might be the same, because universities are also employers).

2 of 5
3

Comparing objects with different fields sounds like bad polymorphic design, whether it's Java or any other OOP language:

  • If your comparator needs to know the precise subtype of an object to do the comparison, you mess-up with the the open-closed principle, since for every new subclassing, you'd potentially need to modify the comparator to select the relevant fields.
  • If your comparator needs uses reflexion to find on its own the relevant fields to compare, you indirectly mess up with the principle of encapsulation, since you create a hidden requirement that information to be compared must be in some predetermined field.

If you want to sort People properly in a clean polymorphic design:

  • you need to rely either on a field, available for any kind of People, including Student, or
  • you may call some function/transformation that provides a unique value (e.g. a string) that allows to sort any People. People and Student may then just use a different transformation that will be passed to the comparator; Or
  • you only sort among homogeneous subtypes.
🌐
GeeksforGeeks
geeksforgeeks.org › java › compare-objects-by-multiple-fields-in-java
How to Compare Objects by Multiple Fields in Java? - GeeksforGeeks
July 23, 2025 - To compare objects by multiple fields in Java using a Custom Comparator, you can follow this approach, Suppose you have a class MyClass with fields field1, field2, and field3.
🌐
InfoWorld
infoworld.com › home › blogs › java challengers
Comparing Java objects with equals() and hashcode() | InfoWorld
May 16, 2024 - The equals() method should compare the whole state of objects: values from fields. The hashcode() method could be the ID of a POJO. When the result of comparing two object’s hashcodes is false, the equals() method should also be false.
🌐
Medium
medium.com › @AlexanderObregon › javas-objects-equals-method-explained-3a84c963edfa
Java’s Objects.equals() Method Explained | Medium
3 weeks ago - Explore Java's Objects.equals() method, a null-safe solution for object comparison. Learn how it prevents NullPointerException and simplifies your code.
Find elsewhere
🌐
Mendix
community.mendix.com › link › spaces › java-actions › questions › 87391
Comparing two objects and showing the changed attributes
July 5, 2017 - The Mendix Forum is the place where you can connect with Makers like you, get answers to your questions and post ideas for our product managers.
🌐
Team Treehouse
teamtreehouse.com › community › java-compareto-sorting-sorting-multiple-fields-for-same-object
Java CompareTo Sorting - Sorting Multiple Fields for Same Object (Example) | Treehouse Community
September 14, 2017 - public class Player implements Comparable<Player> @Override public int compareTo(Player object) { Player other = (Player) object; // We always want to sort by last name then first name if(equals(other)) { return 0; } return lastName.compareTo(other.lastName); } Collections.sort(team.getPlayerList()); Android Development Techdegree Graduate 27,137 Points ... I figured this out, I needed to utilize comparators. Here is a good resource: https://beginnersbook.com/2013/12/java-arraylist-of-object-sort-example-comparable-and-comparator/
🌐
GitHub
github.com › assertj › assertj › issues › 2348
How to recursively compare two objects with different field names but same values · Issue #2348 · assertj/assertj
September 23, 2021 - As for the fields with the same names, comparison is working just fine, for the ones that names differs between the objects, following error is returned: DTO can't be compared to Entity as Entity does not declare all DTO fields, it lacks these: [dtoFieldA, dtoFieldB, dtoFieldC] I've tried following configuration, but without luck: assertThat(DTO) .usingRecursiveComparison(RecursiveComparisonConfiguration.builder() .withEqualsForFields(fieldAPRedicate, "dtoFieldA") .withEqualsForFields(fieldBPRedicate, "dtoFieldB") .withEqualsForFields(fieldCPRedicate, "dtoFieldC") .build()) .isEqualTo(Entity) BiPredicate<DTO, Entity> fieldAPRedicate = (d, e) -> d.dtoFieldA().equals(e.entityFieldA()); BiPredicate<DTO, Entity> fieldBPRedicate = (d, e) -> d.dtoFieldB().equals(e.entityFieldB()); BiPredicate<DTO, Entity> fieldCPRedicate = (d, e) -> d.dtoFieldC().equals(e.entityFieldC());
Author   baadamczyk
🌐
Medium
rathoreaparna678.medium.com › comparing-objects-with-java-reflection-api-aac2b035480
Comparing Objects with Java Reflection API | by Aparna Rathore | Medium
July 10, 2023 - 1. Accessing Fields: — Reflection allows you to access the fields of an object using the `Field` class. You can retrieve the field values using `field.get(object)` and compare them between two objects.
🌐
Apache Commons
commons.apache.org › proper › commons-lang › javadocs › api-3.9 › org › apache › commons › lang3 › builder › EqualsBuilder.html
EqualsBuilder (Apache Commons Lang 3.9 API)
A null superclass is treated as java.lang.Object. If the testRecursive parameter is set to true, non primitive (and non primitive wrapper) field types will be compared by EqualsBuilder recursively instead of invoking their equals() method. Leading to a deep reflection equals test.
🌐
LabEx
labex.io › tutorials › java-how-to-compare-java-objects-based-on-multiple-attributes-417392
How to compare Java objects based on multiple attributes | LabEx
The Comparator<T> interface defines a method compare(T o1, T o2) that compares two objects of the same type. Unlike Comparable, which is implemented by the class being compared, a Comparator is a separate class or lambda expression that can ...
🌐
How to do in Java
howtodoinjava.com › home › java basics › java object equality without public fields or getters
Java Object Equality without Public Fields or Getters
September 11, 2024 - The non-primitives are compared using their equals() method. Transient members are not tested, as they are likely derived fields, and not part of the value of the Object. Static fields are not tested.
🌐
Codemia
codemia.io › knowledge-hub › path › compare_two_objects_in_java_with_possible_null_values
Compare two objects in Java with possible null values
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises
Top answer
1 of 2
3

I think if there were a one-size-fits-all way to compare objects, then Java (or any language) would make it the default, no?

Equality - like hashing and comparison - should be fast, simple and most importantly referentially transparent.

In the end, the question of what exactly the equals method is for is important. If you don't know, then just leave it as is. Physical comparison makes sense in many use cases, particularly if you have control over when objects are created vs. when they are reused.

Also, rather than trying to design comparison functions meaningful for all cases, write code using things like Comparator and let calling code inject whatever makes the most sense at the call site.

2 of 2
3

First of all, there are two kinds of classes:

  • Classes with "value-type" semantics.
  • Classes with "reference" semantics.

You can google these terms to find information about precisely what they mean, and how they differ from each other, for your language of choice.

Every single class with "value-type" semantics must have an equals() method, and this method must take into consideration every single one of its fields, or at least give the illusion that it does so. If it is expensive, bite the bullet and spend clock cycles lavishly, because it is necessary.

Classes with "reference" semantics do not need an equals() method. I would not go as far as to say that they should not have such a method, but if they are to have one, it should be thought of as a utility / helper method which is going to be used in some weird way which is unrelated to the original intent of equals. That's because under normal circumstances, these objects are compared by reference, not by value.

Reference equality is checked using the == operator in Java, while in C#, where the == operator may be overloaded, we use System.Object.ReferenceEquals(). (Though, again, you are not supposed to overload the == operator of a reference-semantics class.)

Incidentally, the kinds of classes that are complex and expensive to check for equality usually tend to be classes with reference semantics, so they do not need an equals() method. And generally, if you have any doubts or second thoughts as to how the equals() method should be implemented, this is a good indication that what you have in your hands is a reference-semantics class, not a value-type-semantics class.

As for hashCode(), the only objects that should implement it are objects that not only have value semantics, but are also immutable. This is because hash containers generally obtain the hash code of an object once, and then cache it for as long as the object resides in the container, so if the object undergoes a mutation, the contents of the object will be in conflict with the cached hash code. It is a very common newbie bug to use a non-immutable object as a key to a hashmap, and a very hard one to track down unless you know where to look first: the immutability of the class used as the key.

So, every class which is not immutable should have a hashCode() method coded as follows:

public int hashCode()
{
    assert false; //OMG! hashCode() was invoked on mutable object!
}

So, since only immutable classes should implement hashCode(), ensuring that it works in a way which is in agreement with how equals() works is pretty straightforward, and probably a lot more simple than what you may have feared.

🌐
Coderanch
coderanch.com › t › 614571 › java › Comparing-dynamic-fields-objects-equals
Comparing dynamic fields of objects using equals and hashCode methods (Java in General forum at Coderanch)
Need: I need to customize this logic such that the fields Names (classificationId, deptId, jobTitleId & locId etc) can be pulled dynamically along with their values. So, as far as my understanding I made use of 2 classes (TableClass and ColWithData) such that the List of ColWithData is there in TableClass object. I'm thinking what if I override the same two methods `equals() & hashCode();` such that the same can be achieved.