Java HashSet with a custom equality criteria? [duplicate]

Solution 1:

Nope, you've found exactly the solution you're supposed to use.

Even for TreeSet, it's frowned upon to use comparison criteria that aren't compatible with equals:

Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface.

I don't know about Apache Commons, but Guava specifically rejected requests for this sort of thing, although you can achieve what you want using Guava Equivalence:

Equivalence<T> equivalence = new Equivalence<T>() {
    @Override
    protected boolean doEquivalent(T a, T b) {
        return CustomComparator.equals(a, b);
    }

    @Override
    protected int doHash(T item) {
        return CustomHashCodeGenerator.hashCode(item);
    }
};
List<T> items = getItems();
Set<Equivalence.Wrapper<T>> setWithWrappedObjects = items.stream()
    .map(item -> equivalence.wrap(item))
    .collect(Collectors.toSet());

Solution 2:

There are a couple of third-party collections frameworks that allows custom equality logic. This is perfect for overriding equality for objects that you can't alter the source.

  • Trove

Trove's maps/sets support the use of custom hashing strategies, allowing you to tune collections based on characteristics of the input data. This feature also allows you to define hash functions when it is not feasible to override Object.hashCode().

  • HE-Collection

To achive this, any type that needs a standard correction, must implement the HE-Collection interface EqualsAndHashCorrection. This interface defines the methods hashCodeInHeCollection() and equalsInHeCollection(Object), that serve as correction for the incorrect implemented methods hashCode() and equals(Object).