Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TreeSet/TreeMap equivalent for HashSet/HashMap (custom hasher)

TreeSet has a constructor that takes a comparator, meaning even if the objects you store aren't Comparable objects by themselves, you can provide a custom comparator.

Is there an analogous implementation of a nonordered set? (e.g. an alternative to HashSet<T> that takes a "hasher" object that calculates equals() and hashCode() for objects T that may be different from the objects' own implementations?)

C++ std::hash_set gives you this, just wondering if there's something for Java.


Edit: @Max brings up a good technical point about equals() -- fair enough; and it's true for TreeMap and HashMap keys via Map.containsKey(). But are there other well-known data structures out there that allow organization by custom hashers?

like image 794
Jason S Avatar asked Dec 16 '11 14:12

Jason S


People also ask

What is the difference between HashSet and TreeSet?

What is Hashset and Tresset? Hashset is the execution of the set interface and is backed by hashmap, while on the other hand, Tree set executes sorted sets and is backed by TreeMap.

Is hashCode used in TreeMap?

hashCode and equals method are not required for TreeSet and TreeMap as the sorting depends on either the compareTo or compare method as been provided by the client.

Is hashmap and HashSet same?

Hashmap is the implementation of Map interface. Hashset on other hand is the implementation of set interface. Hashmap internally do not implements hashset or any set for its implementation. Hashset internally uses Hashmap for its implementation.

Is TreeSet faster than HashSet?

Simply put, HashSet is faster than the TreeSet. HashSet provides constant-time performance for most operations like add(), remove() and contains(), versus the log(n) time offered by the TreeSet.


2 Answers

No, having a "hasher" object is not supported by the Collections specifications. You can certainly implement your own collection that supports this but another way to do this is to consider the Hasher to be a wrapping object that you store in your HashSet instead.

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

The wrapper class would then look something like:

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
    }
}
like image 199
Gray Avatar answered Sep 24 '22 00:09

Gray


There is no such implementation in the standard library, but it doesn't prevent you from rolling your own. This is something i've often wanted to have myself.

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

We wanted to avoid the complexity. We seriously entertained this notion at the time the collections framework was designed, but rejected it. The power-to-weight ration seemed to low. We felt that equals was what you wanted 95% of the time; ==, 4%; and something else 1%. Writing sensible contracts for bulk operations when is very tricky when equality predicates differ.

like image 32
Christoffer Hammarström Avatar answered Sep 25 '22 00:09

Christoffer Hammarström