Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LinkedIdentityHashSet

I know both the IdentityHashSet (via Collections#newSetFromMap(Map))and the LinkedHashSet. However, what I need is a combination of the two, a LinkedIdentityHashSet. I could not find any ready-made solution on the net. Anybody knows how to tweak this?

Thanks for advice!

like image 496
Rafael Winterhalter Avatar asked Jun 24 '13 13:06

Rafael Winterhalter


2 Answers

The implementation techniques there don't marry up very well. LinkedHashMap adds linked listing to the entry objects of the map. IdentityHashMap uses a probing technique and so avoids having any entry objects.

There's a few ways to add "identity" characteristics to a collection/map.

  • Force the key type to behave correctly with final equals and hashCode methods. Really all reference-type types should have this, but never mind.
  • If you can't modify equals and hashCode but can modify the class, add a final field that is of a final class that holds a final references to the type you were going to use as the key. Use the new field as the key.
  • Store adaptor objects in the collection/map. You will need to create a new adaptor instance for each lookup. It just has its equals/hashCode methods to call ==/System.identityHashCode on the original object.
like image 153
Tom Hawtin - tackline Avatar answered Sep 28 '22 00:09

Tom Hawtin - tackline


One option is to use LinkedHashSet and a wrapper

class LinkedIdentityHashSet<E> extends AbstractSet<E> {
    Set set = new LinkedHashSet();

    static class IdentityWrapper {
        Object obj;

        IdentityWrapper(Object obj) {
            this.obj = obj;
        }

        public boolean equals(Object obj) {
            return this.obj == obj;
        }

        public int hashCode() {
            return System.identityHashCode(obj);
        }
    }

    public boolean add(E e) {
        return set.add(new IdentityWrapper(e));
    }
...
like image 27
Evgeniy Dorofeev Avatar answered Sep 28 '22 01:09

Evgeniy Dorofeev