The basic question here is "How can you determine if two objects are equal to each other?"
This is a simple question for simple objects. However, it becomes increasingly difficult with even slightly more complex objects.
As stated in the original question:
The only unique thing about the object is the the map myMap which gets populated later in the lifecycle.
Given two instances of the type MyObject, the member variables myMap must be compared with each other. This map is of type Map<String, String>. A few questions immediately come to mind:
- How do the keys & values define equality?
- (does a key=value pair need to be compared as a unit?)
- (or should only the values be compared to each other?)
- How does the order of the keys in the map affect equality?
- (should keys in the list be sorted, so that A-B-C is equivalent to B-C-A?)
- (or does 1-2-3 mean something different than 3-2-1?)
- Does upper/lower case make any different to the equality of the values?
- Will these objects ever be stored in some kind of Java HashSet or Java TreeSet?
- (do you need to store the same object several times in the same collection?)
- (or should objects with equal hashcodes only be stored once?)
- Will these objects ever require sorting as part of a list or Java Collection?
- How should the comparison function arrange non-equal objects in a list?
- (how should key order determine if an object will come earlier or later in a list?)
- (how should values determine order, especially if several values are different?)
Answers to each of these questions will vary between applications. In order to keep this applicable to a general audience, the following assumptions are being made:
- To maintain a deterministic comparison, keys will be sorted
- Values will be considered to be case-sensitive
- Keys and values are inseparable, and will be compared as a unit
- The Map will be flattened into a single String, so results can be compared easily
The beauty of using equals(), hashCode(), and compareTo() is that once hashCode() is implemented properly, the other functions can be defined based on hashCode().
Considering all of that, we have the following implementation:
@Override
public boolean equals(final Object o)
{
if (o instanceof MyObject)
{
return (0 == this.compareTo(((MyObject) o)));
}
return false;
}
@Override
public int hashCode()
{
return getKeyValuePairs(this.myMap).hashCode();
}
// Return a negative integer, zero, or a positive integer
// if this object is less than, equal to, or greater than the other object
public int compareTo(final MyObject o)
{
return this.hashCode() - o.hashCode();
}
// The Map is flattened into a single String for comparison
private static String getKeyValuePairs(final Map<String, String> m)
{
final StringBuilder kvPairs = new StringBuilder();
final String kvSeparator = "=";
final String liSeparator = "^";
if (null != m)
{
final List<String> keys = new ArrayList<>(m.keySet());
Collections.sort(keys);
for (final String key : keys)
{
final String value = m.get(key);
kvPairs.append(liSeparator);
kvPairs.append(key);
kvPairs.append(kvSeparator);
kvPairs.append(null == value ? "" : value);
}
}
return 0 == kvPairs.length() ? "" : kvPairs.substring(liSeparator.length());
}
All the critical work is being done inside of hashCode(). For sorting, the compareTo() function only needs to return a negative/zero/positive number -- a simple hashCode() diff. And the equals() function only needs to return true/false -- a simple check that compareTo() equals zero.
For further reading, there is a famous dialogue by Lewis Carroll on the foundations of logic, which touches on the basic question of equality:
https://en.wikipedia.org/wiki/What_the_Tortoise_Said_to_Achilles
And, in regard to even simple grammatical constructs, there is a fine example of two "equal" sentences at the start of chapter 6, "Pig and Pepper", from Alice in Wonderland:
The Fish-Footman began by producing from under his arm a great letter, and this he handed over to the other, saying, in a solemn tone, "For the Duchess. An invitation from the Queen to play croquet." The Frog-Footman repeated, in the same solemn tone, "From the Queen. An invitation for the Duchess to play croquet." Then they both bowed low and their curls got entangled together.