Remove duplicates without overriding hash method

I have a List that contains a list of objects, and I want to remove from this list all elements that have the same value in their two attributes. I had something like this:

List<Class1> myList;
....
Set<Class1> mySet = new HashSet<Class1>();
mySet.addAll(myList);

      

and overriding the hash method in Class1 so it returns a number that only depends on the attributes I want to consider.

The problem is that I need to do different filtering in a different part of the application, so I cannot override the hash method this way (I need two different hash methods).

What's the most efficient way to do this filtering without overriding the hash method?

thanks

+2


a source to share


5 answers


Overriding hashCode

and equals

in Class1

(only for this) is problematic. You end up with a class that has an unnatural definition of equality, which may differ for other current and future uses of the class.

Review the Comparator interface and write an implementation Comparator<Class1>

to compare instances of yours Class1

based on your criteria; for example based on these two attributes. Then instantiate TreeSet<Class

> `to re-discover using the TreeSet (Comparator) constructor .

EDIT



Comparing this approach to @ Tom Hawtin's:

  • Both approaches use roughly comparable space overall. The inner nodes of the treeet will roughly balance the hashset array and wrappers that support custom equals / hash methods.

  • Wrapping method + hashset O(N)

    over time (assuming good hashing) versus O(NlogN)

    for the trees approach. So this is the way to go if the input list is likely to be large.

  • The tree approach wins in terms of the lines of code that need to be written.

+4


a source


Let yours Class1

realize Comparable

. Then use TreeSet

as in your example (i.e. use a method addAll

).



+3


a source


As an alternative to what Roman said, you can take a look at this SO question about filtering using Predicates. If you are using google collection anyway this might come in handy.

+2


a source


I would suggest introducing a class for the concept of parts Class1

that you want to be considered meaningful in this context. Then use HashSet

or HashMap

.

+1


a source


Sometimes programmers do too complex things, trying to use all the nice features of the language, and the answers to this question are examples. Overriding anything in the class is overkill. You need the following:

class MyClass {
  Object attr1;
  Object attr2;
}

List<Class1> list;
Set<Class1> set=....
Set<MyClass> tempset = new HashSet<MyClass>;

for (Class1 c:list) {
  MyClass myc = new MyClass();
  myc.attr1 = c.attr1;
  myc.attr2 = c.attr2;

  if (!tempset.contains(myc)) {
    tempset.add(myc);
    set.add(c);
  }
}

      

Feel free to commit minor irregularities. There will be some problems depending on what you mean by equality for attributes (and obvious changes if attributes are primitive). Sometimes we need to write code and not just use built-in libraries.

0


a source







All Articles