Comparing Objects
Navigate Collection topic:
)
|
In Java, we can distinguish two kinds of equality.
- Object reference equality : when two object references point to the same object.
- Object value equality : when two separate objects happen to have the same values/state.
Comparing for reference equality [edit]
The ==
operator can be used to check if two object references point to the same object.
Listing 1.1: Reference equality.
![]() |
if (objRef1 == objRef2) {
// The two object references point to the same object } |
Comparing for value equality [edit]
To be able to compare two Java objects of the same class the
method must be overriden and implemented by the class.boolean
equals(Object
obj)
The implementor decides which values must be equal to consider two objects to be equal. For example in the below class, the name
and the address
must be equal but not the description
.
Listing 1.2: Method overriding.
![]() |
public class Customer {
private String name; private String address; private String description; // ... public boolean equals(Object obj) { // if the two objects are equal in reference, they are equal if (this == obj) { return true; } else if (obj instanceof Customer) { Customer cust = (Customer) obj; if (((cust.getName() == null) && (this.getName() == null)) ¦¦ cust.getName().equals(this.getName())) && ((cust.getAddress() == null) && (this.getAddress() == null) ¦¦ cust.getAddress().equals(this.getAddress()))) { return true; } else { return false; } } else { return false; } } } |
After the equals()
method is overriden, two objects from the same class can be compared like this:
Listing 1.3: Method usage.
![]() |
Customer cust1 = new Customer();
Customer cust2 = new Customer(); //... if (cust1.equals(cust2)) { // Two Customers are equal, by name and address } |
Note that some VMs may optimize the number of equals call by using the hashCode method. Therefore, it is advisable to override hashCode together with equals. The hashCode method has to ensure that if two objects are equal, their hash codes must be equal.
Sorting/Ordering [edit]
To be able to sort objects from the same class, the class must implement the Comparable
interface.
Comparable
interface- imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering, and the class's compareTo method is referred to as its natural comparison method.
Since Java 5.0, the Comparable
interface is generic; that means when you implement it, you can specify what your class can be compared to. Usually, this is the same as your class.
Listing 1.4: Comparable class.
![]() |
public class Customer implements Comparable<Customer> {
private String name; private String address; private String description; // ... public int compareTo(Customer cust) { int iRet = (this.getName() + this.getAddress()).compareTo(cust.getName() + cust.getAddress()); return iRet; } } |
In the above code the String
class also implements the Comparable<String>
interface, so the compareTo()
method can be used to compare name
and address
.
int
compareTo(T o)- Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.
Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort). Objects that implement this interface can be used as keys in a sorted map or elements in a sorted set, without the need to specify a comparator.
The natural ordering for a class C is said to be consistent with equals if and only if (e1.compareTo((Object)e2) == 0) has the same boolean value as e1.equals((Object)e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.
Change Sorting/Ordering [edit]
Sometimes we may want to change the ordering of a collection of objects from the same class. We may want to order descending or ascending order. We may want to sort by name
or by address
.
We need to create a class for each way of ordering. It has to implement the Comparator
interface.
Since Java 5.0, the Comparator
interface is generic; that means when you implement it, you can specify what type of objects your comparator can compare.
Listing 1.5: Comparator class.
![]() |
public class CustComparatorByName implements Comparator<Customer> {
public int compare(Customer cust1, Customer cust2) { return cust1.getName().compareTo(cust2.getName()); } } |
The above class then can be associated with a SortedSet or other collections that support sorting.
Listing 1.6: Comparator usage.
![]() |
Collection<Customer> custSetByName = new TreeSet<Customer>(new CustComparatorByName());
|
Using the Iterator the custSetByName
collection can be iterated in order of sorted by name
.
A List can be sorted by the Collections
's sort
method.
Listing 1.7: Customized comparison.
![]() |
import java.util.Collections
//... Collections.sort(custList, new CustComparatorByName()); |
Sorts the specified list according to the order induced by the specified comparator. All elements in the list must be mutually comparable using the specified comparator.
Also an array of objects can be sorted with the help of a Comparator.
Listing 1.8: Array sorting.
![]() |
import java.util.Arrays;
//... Arrays.sort(cust[], new CustComparatorByName()); |
Sorts the specified array of Customer objects (cust[] array) according to the order induced by the specified comparator. All elements in the array must be mutually comparable by the specified comparator.