简体   繁体   中英

Comparing two Lists of a class without iterating the lists

I have a class Abc as below

public class Abc {
  int[] attributes;

  Abc(int[] attributes){
    this.attributes = attributes;
  }
}

Overriding the Abc hash code as below

@Override
public int hashCode() {
    int hashCode = 0;
    int multiplier = 1;
    for(int i = attributes.length-1 ; i >= 0 ; i++){
        hashCode = hashCode+(attributes[i]*multiplier);
        multiplier = multiplier*10;
    }       
    return hashCode;    
}

I am using above class to create a list of objects and I want to compare whether the two lists are equal ie lists having objects with same attributes.

    List<Abc> list1 ;
     list1.add(new Abc(new int[]{1,2,4}));
     list1.add(new Abc(new int[]{5,8,9}));
     list1.add(new Abc(new int[]{3,4,2}));
   List<Abc> list2;       
     list2.add(new Abc(new int[]{5,8,9}));
     list2.add(new Abc(new int[]{3,4,2}));
      list2.add(new Abc(new int[]{1,2,4}));

How can I compare the above two lists with/without iterating over each list . Also is there any better way to override the hashcode , so that two classes having the same attributes(values and order) should be equal.

You have to override the function equals in your class Abc . If you are using an IDE, it can be used to generates something good enough. For example, Eclipse produces the following:

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    }
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    Abc other = (Abc) obj;
    if (!Arrays.equals(attributes, other.attributes)) {
        return false;
    }
    return true;
}

With this equals method, you can now check that two instance of Abc are equal.

If you want to compare your two lists list1 and list2 , unfortunately you can not simply do

boolean listsAreEqual = list1.equals(list2); // will be false

because that would not only check if the elements in the lists are the same but also if they are in the same order. What you can do is to compare two sets, because in sets, the elements have no order.

boolean setAreEqual = new HashSet<Abc>(list1).equals(new HashSet<Abc>(list2)); // will be true.

Note that in that case, you should keep your implementation of hashcode() in Abc , for the HashSet to function well. As a general rule, a class that implements equals should also implement hashcode .

The problem with a Set ( HashSet are Set ) is that by design it will not contain several objects which are equal with each other. Objects are guaranteed to be unique in a set. For example, if you add a new new Abc(new int[]{5,8,9}) in the second set, the two sets will still be equal.

If it bothers you then the possible solution is either to compare two lists, but after having sorted them beforehand (for that you have to provide a comparator or implements compareTo ), or use Guava's HashMultiset , which is an unordered container that can contain the same objects multiple times.

Override the equals method to compare objects. As the comments mention, you should be overriding the hashcode method as well when overriding equals method.

By this

so that two classes having the same attributes(values and order) should be equal.

i think you mean two objects having same attributes.

you can try something like this

public boolean equals(Object o) {
  if(!(Object instanceOf Abc)) {
    return false;
  }
  Abc instance = (Abc)o;
  int[] array = instance.attributes;
  for(i=0;i<array.length;i++){
      if(array[i]!=this.attributes[i]) {
        return false;
      }
  }
}

Edit: As for the hashcode the concept is that when

object1.equals(object2)

is true, then

object1.hashcode()

and

object2.hashcode() 

must return the same value. and hashCode() of an object should be same and consistent through the entire lifetime of it. so generating hashcode based on the value of its instance variables is not a good option as a different hashcode may be generated when the instance variable value changes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM