Search code examples
javagenericsgeneric-listgeneric-programminggeneric-collections

Unique classes in generic list


I have a generic class with a generic list in it. I want to ensure that the generic list only contains unique classes.

What I have done so far is to compare the class names with reflection (getClass()). But I think that's not a clean solution. Are there any better practices to check?

public class MyGenericClass<T extends MyGenericClass.MyInterface> {
  private List<T> members = new ArrayList<>(0);

  public void add(T t) {
    final boolean[] classInMembers = {false};

    members.forEach(member -> {
      if (member.getClass().getName().equals(t.getClass().getName())) {
        classInMembers[0] = true;
      }
    });

    if (!classInMembers[0]) {
      members.add(t);
    }
  }

  public interface MyInterface {
    void doSomething(String text);
  }
}
public class Main {
  public static void main(String[] args) {
    MyGenericClass<MyGenericClass.MyInterface> myGenericClass = new MyGenericClass<>();

    myGenericClass.add(new Performer1());
    myGenericClass.add(new Performer2());
    myGenericClass.add(new Performer3());
    myGenericClass.add(new Performer3()); // should not be inserted!
  }

  private static class Performer1 implements MyGenericClass.MyInterface {
    @Override
    public void doSomething(String text) {
      text = "Hi, I am performer 1!";
    }
  }

  private static class Performer2 implements MyGenericClass.MyInterface {
    @Override
    public void doSomething(String text) {
      text = "Hi, I am performer 2!";
    }
  }

  private static class Performer3 implements MyGenericClass.MyInterface {
    @Override
    public void doSomething(String text) {
      text = "Hi, I am performer 3!";
    }
  }
}

Solution

  • You could subclass a java.util.Set interface implementation. It will likely be easiest to subclass java.util.AbstractSet.

    By default 'Set' will compare objects by their .equals() method - In your case, this is not sufficient. You will need to override the contains method to ensure that only instances of a unique class are added.

    In your overrideen contains, it's probably the same / easier to compare class instances rather than their stringified package name

    I.e. use a.getClass() == b.getClass(), rather than a.getClass().getName()