Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two Java Collections using Comparator instead of equals()

Problem Statement

I have two Collections of the same type of object that I want to compare. In this case, I want to compare them based on an attribute that does not factor into equals() for the Objects. In my example, I'm using ranked collections of Names for instance:

public class Name {
    private String name;
    private int weightedRank;

    //getters & setters

    @Override
    public boolean equals(Object obj) {
        return this.name.equals(obj.name); //Naive implementation just to show
                                           //equals is based on the name field.
    }
}

I want to compare the two Collections to assert that, for position i in each Collection, the weightedRank of each Name at that position is the same value. I did some Googling but didn't find a suitable method in Commons Collections or any other API so I came up with the following:

public <T> boolean comparatorEquals(Collection<T> col1, Collection<T> col2,
        Comparator<T> c)
{
    if (col1 == null)
        return col2 == null;
    if (col2 == null) 
        return false;

    if (col1.size() != col2.size())
        return false;

    Iterator<T> i1 = col1.iterator(), i2 = col2.iterator();

    while(i1.hasNext() && i2.hasNext()) {
        if (c.compare(i1.next(), i2.next()) != 0) {
            return false;
        }
    }

    return true;
}

Question

Is there another way to do this? Did I miss an obvious method from Commons Collections?

Related

I also spotted this question on SO which is similar though in that case I'm thinking overriding equals() makes a little more sense.

Edit

Something very similar to this will be going into a release of Apache Commons Collections in the near future (at the time of this writing). See https://issues.apache.org/jira/browse/COLLECTIONS-446.

like image 420
Matt Lachman Avatar asked Feb 26 '13 16:02

Matt Lachman


People also ask

How does Compare method of Comparator work in Java?

The compare Method obj1 and obj2 are the objects to be compared. This method returns zero if the objects are equal. It returns a positive value if obj1 is greater than obj2. Otherwise, a negative value is returned.

How do I use Comparator in collections sort?

Using a comparator, we can sort the elements based on data members. For instance, it may be on roll no, name, age, or anything else. Method of Collections class for sorting List elements is used to sort the elements of List by the given comparator.

What is the use of equals method in Comparator?

Indicates whether some other object is "equal to" this comparator. This method must obey the general contract of Object. equals(Object) . Additionally, this method can return true only if the specified object is also a comparator and it imposes the same ordering as this comparator.

Which classes have Comparator () method?

Java Comparator interface is used to order the objects of a user-defined class. This interface is found in java. util package and contains 2 methods compare(Object obj1,Object obj2) and equals(Object element).


1 Answers

You could use the Guava Equivalence class in order to decouple the notions of "comparing" and "equivalence". You would still have to write your comparing method (AFAIK Guava does not have it) that accepts an Equivalence subclass instead of the Comparator, but at least your code would be less confusing, and you could compare your collections based on any equivalence criteria.

Using a collection of equivance-wrapped objects (see the wrap method in Equivalence) would be similar to the Adapter-based solution proposed by sharakan, but the equivalence implementation would be decoupled from the adapter implementation, allowing you to easily use multiple Equivalence criteria.

like image 161
lbalazscs Avatar answered Nov 12 '22 01:11

lbalazscs