14

Let say I have two different hashsets as shown below how can I check that two Hashset contain the same elements and these two hashsets are equal, independent of the order of elements in collection, please advise..!!

Set set1=new HashSet();
          set.add(new Emp("Ram","Trainer",34000));
          set.add(new Emp("LalRam","Trainer",34000));

and the other one is ..

Set set2=new HashSet();
          set.add(new Emp("LalRam","Trainer",34000));
          set.add(new Emp("Ram","Trainer",34000));

The employee pojo is ...

class Emp //implements Comparable
{
      String name,job;
      public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getJob() {
        return job;
    }
    public void setJob(String job) {
        this.job = job;
    }
    public int getSalary() {
        return salary;
    }
    public void setSalary(int salary) {
        this.salary = salary;
    }
    int salary;
      public Emp(String n,String j,int sal)
      {
         name=n;
         job=j;
         salary=sal;
       }
      public void display()
      {
        System.out.println(name+"\t"+job+"\t"+salary);
       }



  public boolean equals(Object o)
      {

         Emp p=(Emp)o;
          return this.name.equals(p.name)&&this.job.equals(p.job) &&this.salary==p.salary;
       }
   public int hashCode()
       {
          return name.hashCode()+job.hashCode()+salary;
       }


      /* public int compareTo(Object o)
       {
          Emp e=(Emp)o;
          return this.name.compareTo(e.name);
           //return this.job.compareTo(e.job);
        //   return this.salary-e.salary;

        }*/
} 
user1582269
  • 285
  • 1
  • 6
  • 12
  • 3
    First define "equals". Equals reference or equuivalent? If the latter, is equals and hashcode define for the Emp class? – MJB Aug 09 '12 at 17:14
  • Assuming `Emp` has proper overrides for `equals()` and `hashCode()` (which it probably does, given its presence in a hash table) you could compare counts on the sets, and then try to add every element of one set to the other. If the `add()` method ever returns `true`, then there's a difference. – dlev Aug 09 '12 at 17:15
  • This is no different than comparing any other collections. See: http://stackoverflow.com/questions/50098/comparing-two-collections-for-equality. While this is .net, the java implementation should be pretty much the same. I recommend Daniel Jennings or mbillings answer as I'm pretty sure the highest voted answer violates Microsofts terms of use. – Ian Dallas Aug 09 '12 at 17:16
  • First, is is not meaningful to discuss element order in a `Set`. Sets have no implicit order. Second, you haven't specified what you mean by "equals". For collections, it could be _"the two collections contain the same set of references to actual elements"_, or _"All elements from collection A compare equal (via `equals()`) to their corresponding element in collection B"_. You seem to want the latter definition, which is trickier to implement. – Jim Garrison Aug 09 '12 at 17:27
  • This question is a duplicate and the right answer is here: http://stackoverflow.com/questions/1565214/is-there-a-way-to-check-if-two-collections-contain-the-same-elements-independen – Gismo Ranas Oct 24 '13 at 13:02

8 Answers8

103

Quoting from AbstractSet.equals(Object) javadoc:

Returns true if the given object is also a set, the two sets have the same size, and every member of the given set is contained in this set. This ensures that the equals method works properly across different implementations of the Set interface.

So it's sufficient to simply call set1.equals(set2). It will return true if and only if the set contain the same elements (assuming that you have correctly defined equals and hashCode on the objects in the sets).

Petr
  • 62,528
  • 13
  • 153
  • 317
10

Assuming you've defined equals and hashcode, here's one way. Not very efficient for large members.

  1. Check the # of elements in each. If they are not equal, you are done [not equal].
  2. Loop through Set1. Check if Set2 contains each element, if not you are done [not equal]. otherwise if you get through the whole set, you are equal

UPDATE: I didn't know about containsAll, which saves a lot of trouble and basically does that algorithm

int s1 = set1.size();
int s2 = set2.size();
if (s1 !=s2) return false;
return set1.containsAll(set2);
MJB
  • 9,352
  • 6
  • 34
  • 49
10

Use the below expression.

set1.containsAll(set2) && set2.containsAll(set1)
Aaron Kurtzhals
  • 2,036
  • 3
  • 17
  • 21
  • 10
    That would be more expensive than doing one containsAll prefixed by a size check, I would think. – MJB Aug 09 '12 at 17:25
4

If you want data equality then correctly implement equals() and hashCode() and then you can use Collection.containsAll(...). Ofcourse, you need to make sure you call this only when both of your collections have the same number of elements otherwise you can just say they aren't equal.

Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
0

Do:

  setResult = set2.clone();

  if ( setResult.retainAll( set1 ) ){

   //do something with results, since the collection had differences

}
Edmon
  • 4,752
  • 4
  • 32
  • 42
0

1 - Get a collection(let's name it 'differences') that will contain items one collection has and another doesn't -

Collection differences = CollectionUtils.subtract(Collection1, Collection2);

2 - Check that size == 0;

If so - both collections have same elements; if no - there's some differences and then you have to print all items that 'differences' has.

Not sure if it depends on items order. I'm comparing collections in this way

0

A verbose but (hopefully) efficient solution when you don't know the types of the collections:

public static <T> boolean equalIgnoreOrder(Collection<T> c1, Collection<T> c2) {
    int size1 = c1.size();  // O(1) for most implementations, but we cache for the exceptions.
    if (size1 != c2.size()) {
        return false;
    }
    Set<T> set;
    Collection<T> other;
    if (c1 instanceof Set) {
        set = (Set<T>) c1;
        other = c2;
    } else if (c2 instanceof Set) {
        set = (Set<T>) c2;
        other = c1;
    } else if (size1 < 12 ) { // N^2 operation OK for small N
        return c1.containsAll(c2);
    } else {
        set = new HashSet<>(c1);
        other = c2;
    }
    return set.containsAll(other);  // O(N) for sets
}
Tad
  • 4,668
  • 34
  • 35
-5

Unless you need to implement your own method for some reason, just use h1.equals(h2). A possible implementation is described below.

  1. Check if # of elements is the same. If not, return false.
  2. Clone set 2 (if you need to keep set 2 after)
  3. Iterate through set 1, check if each element is found in clone set 2. If found, remove from set 2. If not found, return false.
  4. If you reach the end of the iterations and have matched each element of set 1, the sets are equal (since you already compared the sizes of the 2 sets).

Example:

public boolean isIdenticalHashSet <A> (HashSet h1, HashSet h2) {
    if ( h1.size() != h2.size() ) {
        return false;
    }
    HashSet<A> clone = new HashSet<A>(h2); // just use h2 if you don't need to save the original h2
    Iterator it = h1.iterator();
    while (it.hasNext() ){
        A = it.next();
        if (clone.contains(A)){ // replace clone with h2 if not concerned with saving data from h2
            clone.remove(A);
        } else {
            return false;
        }
    }
    return true; // will only return true if sets are equal
}
ArtOfWarfare
  • 20,617
  • 19
  • 137
  • 193
nyanshak
  • 60
  • 6