Question

I need Set collection, where its items will be identified by items class. Something like ReferenceIdentityMap from Appache Collections, but on class scope i.e. two different instances of same class must be identified as same in this collection.

You know, it is a violation of equals()/hashCode() identity principle but in occasional use it makes sense.

I have done this in simple class backing with Map<Class<? extends E>, E>, but due to simplicity it doesn't implement Set<E>. There may be a more elegant solution, decorator of any Set<E> would be great.

Is there any implementation of such collection there (Apache/Google/something/... Collections)?

Was it helpful?

Solution

You wish to override the meaning of equals() / hashCode() for your set members. The cleanest way to do this, I imagine, is to use a wrapper class:

class Wrapper<E> {

  private final E item;

  Wrapper(E item) {
    this.item = item;
  }

  E getItem() {
    return item;
  }

  public boolean equals(Object o) {
    if (!(o instanceof Wrapper)) {
      return false;
    }
    return getClass().equals(o.getClass());
  }

  public int hashCode() {
    return getClass().hashCode();
  }

}

You would create a Set<Wrapper<E>> then.

OTHER TIPS

How about extending HashSet and overriding just the add(..) method, putting object.getClass() instead of the object itself in an inner Set<Class<? extends E>>, and if it succeeds, adding the item itself. Something like

public class ClassSet<E> extends HashSet<E> {
    private Set<Class<? extends E>> classSet = new HashSet<Class<? extends E>>();

    @Override
    public boolean add(E element) {
        if (classSet.add((Class<E>) element.getClass())) {
            return super.add(element); // this actually should always return true
        }
        return false;
    }
}

You can create a Comparator class and construct your set with it in mind. The only condition you must not violate is that for every two elements you try to add, compare(e1, e2) should not throw a ClassCastException - which means that every two members you would try to insert should be comparable.

The comparator class itself should look only at the objects' classes, so it will be safe.

Check out the constructor here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top