I recently ran into a problem where I wanted to add objects attained by reflection to a TreeSet. In this specific case, I had a problem when a Locale object was retrieved. It could not be added to the TreeSet because it is not "Comparable." It did, however, have toString values that could be sorted intelligibly.
I decided to create a Comparator that would handle arbitrary objects, and allow them to be added to a TreeSet of type Object:
package com.threeleaf.util; | |
import java.util.Comparator; | |
/** | |
* A {@link Comparator} that allows any two objects to be sorted based on {@link Object#toString()}. | |
* This works best when the object's toString returns something meaningful, but can still be | |
* useful in cases where a object one has not control over needs to be placed in a sorted | |
* collection. | |
* <p> | |
* Usage: | |
* <pre>{@code | |
* final Set<Object> set = new TreeSet<>(new ToStringComparator()); | |
* // en_US | |
* set.add(Locale.US); | |
* // en_CA | |
* set.add(Locale.CANADA); | |
* // en | |
* set.add(Locale.ENGLISH); | |
* }</pre> | |
* produces the sorted set: {@code [ENGLISH, CANADA, US]} instead of an exception. | |
*/ | |
@SuppressWarnings("WeakerAccess") | |
public class ToStringComparator implements Comparator<Object> | |
{ | |
/** Instantiate a new {@link ToStringComparator}. */ | |
public ToStringComparator() | |
{ | |
super(); | |
} | |
/** {@inheritDoc}. */ | |
public int compare(final Object object1, final Object object2) | |
{ | |
return object1.toString().compareTo(object2.toString()); | |
} | |
} |
The caveat is that this works best when the object in question overrides the default toString method in a meaningful way. If the base Object.toString() method is inherited by the object, then the sorting will most likely appear random, since the method looks like this:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
No comments:
Post a Comment