Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java HashSet with a custom equality criteria? [duplicate]

Tags:

java

set

hashset

I was looking for something akin to the Java TreeSet's ability to receive a custom comparator at instantiation time, so I needed not to use the object's default equality (and hash code) criteria.

The closest I could come up with was to wrap my objects in a private custom class, but that seems hacky :( This ends up being a kind of recurring theme when programming, so I was wondering if there's something already available for us to use. Maybe in the commons libraries?

Thanks

like image 591
devoured elysium Avatar asked Feb 14 '13 17:02

devoured elysium


People also ask

Can HashSet have duplicate objects?

HashSet is an implementation of Set Interface which does not allow duplicate value. The main thing is, objects that are stored in HashSet must override equals() for check for equality, and hashCode() methods for no duplicate value are stored in our set.

How does HashSet find duplicates in Java?

By using HashSet, a general-purpose Set implementation, we can find duplicates in O(n) time. All you need to do is iterate over an array using advanced for loop and insert every element into HashSet. Since it allows only unique elements, add() method will fail and return false when you try to add duplicates.

How HashSet eliminate duplicate user defined objects?

The easiest way to remove repeated elements is to add the contents to a Set (which will not allow duplicates) and then add the Set back to the ArrayList: List<String> al = new ArrayList<>(); // add elements to al, including duplicates Set<String> hs = new HashSet<>(); hs. addAll(al); al. clear(); al.

Does Set allow duplicate objects in Java?

A Set is a Collection that cannot contain duplicate elements. It models the mathematical set abstraction. The Set interface contains only methods inherited from Collection and adds the restriction that duplicate elements are prohibited.


2 Answers

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()); 
like image 75
Louis Wasserman Avatar answered Sep 21 '22 15:09

Louis Wasserman


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).

like image 38
Steve Kuo Avatar answered Sep 22 '22 15:09

Steve Kuo