Equivalent to TreeSet / TreeMap for HashSet / HashMap (custom hash)

TreeSet has a constructor that accepts a comparator, which means that even if the objects you store are not Comparable objects on their own, you can provide a custom comparator.

Is there a similar implementation of an unordered set? (for example, an alternative to HashSet<T> that accepts a "hasher" object that computes equals() and hashCode() for T objects that may differ from their own object implementations?)

C ++ std::hash_set gives you this, just wondering if there is anything for Java.


Edit: @Max brings up a good technical point about equals() - fairly fair; and this is true for the TreeMap and HashMap keys through Map.containsKey() . But are there other well-known data structures that allow organizations using custom hackers?

+7
source share
4 answers

No, the presence of a "hash" of an object is not supported by the Collections specifications. You can, of course, implement your own collection that supports this, but another way to do this is to consider Hasher as a wrapper object that you store in your HashSet .

 Set<HasherWrapper<Foo>> set = new HashSet<HasherWrapper<Foo>>(); set.add(new HasherWrapper(foo)); ... 

The wrapper class will look something like this:

 private class HasherWrapper<T> { T wrappedObject; public HasherWrapper(T wrappedObject) { this.wrappedObject = wrappedObject; } @Override public int hashCode() { // special hash code calculations go here } @Override public boolean equals(Object obj) { // special equals code calculations go here } } 
+9
source

There is no such implementation in the standard library, but this does not stop you from moving on your part. This is what I often wanted to have.

See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4771660 for this reason:

We wanted to avoid complexity. We took this concept seriously at the time the collection structure was developed, but rejected it. power to weight ratio seemed low. We felt that what you wanted was 95% of the time; ==, 4%; and something else 1%. Writing reasonable bulk contracts when it is very difficult when equality predicates vary.

+4
source

No, no, and cannot be a specification. In addition, you misunderstood how TreeSet uses its Comparator .

From TreeSet Javadoc :

Note that the ordering supported by the set (regardless of the comparator) must be matched if it correctly implements the Set interface. (See Comparable or Comparator for an exact definition consistent with peers.) This is because the Set interface is defined in terms of the equality operation, but the TreeSet instance does all the element comparisons using compareTo (or compare), so the two elements that are considered equal by from this point of view, they are equal to this method. the behavior of the set is well defined, even if its ordering is incompatible with equals; it simply does not obey the general contract Set interface.

From comparable javadoc :

A natural ordering for a class C is called consistent with if and only if e1.compareTo (e2) == 0 has the same logical value as e1.equals (e2) for all e1 and e2 of class C. Note that null is not is an instance of any class, and e.compareTo (null) should NullPointerException, although e.equals (null) returns false.

From the javadoc Collection :

boolean contains (Object o)

Returns true if this collection contains the specified item. More formally returns true if and only if the collection contains at least one element e such that (o == null? E == null: o.equals (e)).

Therefore, by specification, there can be no class that implements the Collection<E> interface and is completely dependent on some external object in the Comparator style for inserting objects. All collections should use the equals method of the Object class to check if the object has already been inserted.

+1
source

There is nothing like this, hashcode() and equals() define the attributes of an object and should not be changed. They determine what makes an object equal to each other, and this should not differ from one set to another. The only way to do what you are talking about is to subclass the object and write new hashcode() and equals() , and that would be really wise if the subclass had a defining variable that should be added in addition to the super class' hashcode() and equals() . I know this may not be what you are aiming for, but I hope this helps. If you explain your arguments about this, then it can help you find the best solution, if one exists.

0
source

All Articles