Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing a HashSet using the HashCode directly? (Java)

Hi I'm wondering if it is possible to access the contents of a HashSet directly if you have the Hashcode for the object you're looking for, sort of like using the HashCode as a key in a HashMap.

I imagine it might work something sort of like this:

MyObject object1 = new MyObject(1); 

Set<MyObject> MyHashSet = new HashSet<MyObject>();

MyHashSet.add(object1)

int hash = object1.getHashCode

MyObject object2 = MyHashSet[hash]???

Thanks!

edit: Thanks for the answers. Okay I understand that I might be pushing the contract of HashSet a bit, but for this particular project equality is solely determined by the hashcode and I know for sure that there will be only one object per hashcode/hashbucket. The reason I was pretty reluctant to use a HashMap is because I would need to convert the primitive ints I'm mapping with to Integer objects as a HashMap only takes in objects as keys, and I'm also worried that this might affect performance. Is there anything else I could do to implement something similar with?

like image 787
Kode47 Avatar asked Nov 18 '14 04:11

Kode47


People also ask

How is hashCode used in HashSet?

When we put an object into a HashSet, it uses the object's hashcode value to determine if an element is not in the set already. Each hash code value corresponds to a certain bucket location which can contain various elements, for which the calculated hash value is the same.

Does Java HashSet use equals or hashCode?

If the HashSet has 16 buckets then the bucket is calculated hashCode % 16. If there are already entries in a bucket, then hashCode will compare all entries using the equals method.

Why HashSet has no get method?

HashSet can not guarantee insertion order so no point in get method. What are you missing is implementing equals and use contains() which will iterate and find the object.

What is an efficient and correct way to preview information from a HashSet?

The only information we can derive from the HashSet object is whether the element is present in the HashSet Object or not . If the element is not present in the HashSet then add it otherwise return true leaving HashSet object unchanged. Here, contains() method helps to provide this information.


2 Answers

The common implementation of HashSet is backed (rather lazily) by a HashMap so your effort to avoid HashMap is probably defeated.

On the basis that premature optimization is the root of all evil, I suggest you use a HashMap initially and if the boxing/unboxing overhead of int to and from Integer really is a problem you'll have to implement (or find) a handcrafted HashSet using primitive ints for comparison. The standard Java library really doesn't want to concern itself with boxing/unboxing costs. The whole language sold that performance issue for a considerable gain in simplicity long ago. Notice that these days (since 2004!) the language automatically boxes and unboxes which reveals a "you don't need to be worrying about this" policy. In most cases it's right.

I don't know how 'richly' featured your HashKeyedSet needs to be but a basic hash-table is really not too hard.

like image 114
Persixty Avatar answered Sep 30 '22 19:09

Persixty


HashSet is internally backed by a HashMap, which is unavailable through the public API unfortunately for this question. However, we can use reflection to gain access to the internal map and then find a key with an identical hashCode:

private static <E> E getFromHashCode(final int hashcode, HashSet<E> set) throws Exception {
    // reflection stuff
    Field field = set.getClass().getDeclaredField("map");
    field.setAccessible(true);

    // get the internal map
    @SuppressWarnings("unchecked")
    Map<E, Object> interalMap = (Map<E, Object>) (field.get(set));

    // attempt to find a key with an identical hashcode
    for (E elem : interalMap.keySet()) {
        if (elem.hashCode() == hashcode) return elem;
    }
    return null;
}

Used in an example:

HashSet<String> set = new HashSet<>();
set.add("foo"); set.add("bar"); set.add("qux");

int hashcode = "qux".hashCode();

System.out.println(getFromHashCode(hashcode, set));

Output:

qux
like image 44
August Avatar answered Sep 30 '22 21:09

August