1

I have a method that takes in two lists - both of type Person. The Person class has a large number of attributes but I want to check if the lists contain the same items based on the name and age attributes only, returning true if they are equal and false otherwise.

Is there any nicer way I can be doing this?:

public boolean compareTwoLists(List<Person> list1, List<Person> list2)
{
    for (Person person1 : list1)
    {
        for (Person person2 : list2)
        {
            if (person1.getAge().equals(person2.getAge() && person1.getName().equals(person2.getName())))
            {
                return true;
            }
        }
    }
    return false;
}
thatguy
  • 21,059
  • 6
  • 30
  • 40
ct2602
  • 85
  • 1
  • 2
  • 7

6 Answers6

1

Both solutions below are in Java 8. I prefer the first one because you don't mess with the Person class. But, if you are absolutely sure you will not break anything, the second solution is clearer for the reader.

Solution 1

public boolean compareTwoLists(List<Person> list1, List<Person> list2) {

    return list2.stream().anyMatch(l2 -> list1.stream().anyMatch(l1 ->
         l1.getName().equals(l2.getName()) &&
         l1.getAge().equals(l2.getAge())
    ));
}

Solution 2

public boolean compareTwoLists(List<Person> list1, List<Person> list2) {
    return list2.stream().anyMatch(list1::contains);
}

This means that you need to implement your own equals and hashcode inside the Person object.

@Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;

        Person person = (Person) o;

        if (age != null ? !age.equals(person.age) : person.age != null)
            return false;
        return name != null ? name.equals(person.name) : person.name == null;
    }

    @Override
    public int hashCode()
    {
        int result = age != null ? age.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        return result;
    }
Reveka
  • 91
  • 1
  • 9
0

Override Object.equals() in your Person class so that person1.equals(person2) returns true/false depending on your member values.

SporreKing
  • 483
  • 3
  • 14
0

Check out this answer.

You should implement Comparable . Assuming all fields will not be null (for simplicity sake), that age is an int, and compare ranking is last, first, age, the compareTo method is quite simple:

public int compareTo(Person other) {
    int i = firstName.compareTo(other.firstName);
    if (i != 0) return i;

    i = lastName.compareTo(other.lastName);
    if (i != 0) return i;

    return Integer.compare(age, other.age);
}

You could also @Override your equals Method to make it check for age and name like this

public boolean equals(Object p) {
    ... // More code here - null checks
    if(p.getName().equals(this.name) && p.getAge() == this.age) 
       return true;
    else 
       return false;
}
Community
  • 1
  • 1
mammago
  • 247
  • 2
  • 13
0

If you want to compare the two lists, you will have to iterate both, but if your lists are sorted and you only want to know, if they are equal or not, then you only have to check each list element of both lists once, which should be much faster in the end for large lists:

public boolean compareTwoLists(List<Person> list1, List<Person> list2) {

    // Lists don't have the same size, objects missing in
    // list one or two. I your lists have the same size, skip this.
    if (list1.size() != list2.size() {
        return false;
    }

    Iterator<Person> it1= list1.iterator();
    Iterator<Person> it2= list2.iterator();

    while (it1.hasNext()) {
        Person person1 = it1.next();
        Person person2 = it2.next();

        // Age or name do not match, objects differ, lists are not equal.
        if ((!person1.next().getAge().equals(person2.getAge()) || (!person1.getName().equals(person2.getName()))))
            return false;
    }

    // All items are the same.
    return true;

}

Furthermore, you could write your method as Comparator, which makes it more reusable or suitable for sorting, because you can return 0 (lists are equal), -1 (first list is smaller), 1 (first list is larger) or other meanings for your purpose:

class PersonListComparator implements Comparator<List<Person>> {
    @Override public int compare(List<Person> list1, List<Person> list2) {
        // Your code
    }
}

You could also think about overriding the equals(...) method of the Person class, if you always compare the name and age. Then, the comparison could be shortened to person1.equals(person2) in your code.

Alternatively, use the Comparable interface, which adds a method int compareTo(T object) to your class that does the same as the Comparator.

thatguy
  • 21,059
  • 6
  • 30
  • 40
  • Added a faster alternative with sorting, if your intention is to check the equality of both lists. – thatguy Dec 12 '16 at 15:12
0

You return true as soon as two person have same age and name but it doesn't mean that it is true for all persons.

To achieve it, in your method, you should return false as soon a comparison fails.
When the loops are finished, if you have not returned false, it indicates that all elements have same age and name values. So you return true :

public boolean compareTwoLists(List<Person> list1, List<Person> list2){
  for (Person person1 : list1) {
    for (Person person2 : list2) {
      if (!person1.getAge().equals(person2.getAge() || !person1.getName().equals(person2.getName()))) {
        return false;
      }
    }
  }
  return true;
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
0

From your question i think you just want to check whether given two list contains same data or not (same number of persons and same data) override hashcode and equals methods in Person class to check only name and age.

public class Person {

private String name;
private int age;

// other fields
private String address;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + age;
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Person other = (Person) obj;
    if (age != other.age)
        return false;
    if (name == null) {
        if (other.name != null)
            return false;
    } else if (!name.equals(other.name))
        return false;
    return true;
}}

then just pass the two list in the given function:

public boolean isListEqual(List<Person> list1, List<Person> list2) {
    if (list1.size() != list2.size()) {
        return false;
    } else {
        for (Person p : list1) {
            if (!list2.contains(p)) {
                return false;
            }
        }
        return true;
    }
}
  • It checks if both are of same length else returns false
  • else all the persons from first list should be present in second list if not then return false.
Abhijeet
  • 11
  • 2