How can I perform an independent check of orders in lists?

I want to implement the equals method in a class where the equality of instances comes from the "weak" equality of the contained lists, i.e. e. the same order of list items is not needed, whereas java.util.List.equals(Object) (you can see its javadoc below) requires the same order.

So what is the best way to do an independent check on the lists?


I thought about packing lists into new lists, sorting them, and then doing equal there.

Or another approach (which will make this question obsolete): use TreeSet instead, so the order of the elements will always be the same in sets with equal elements.

 /** * Compares the specified object with this list for equality. Returns * <tt>true</tt> if and only if the specified object is also a list, both * lists have the same size, and all corresponding pairs of elements in * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null : * e1.equals(e2))</tt>.) In other words, two lists are defined to be * equal if they contain the same elements in the same order. This * definition ensures that the equals method works properly across * different implementations of the <tt>List</tt> interface. * * @param o the object to be compared for equality with this list * @return <tt>true</tt> if the specified object is equal to this list */ boolean equals(Object o); 

I know the answer and closed the tab. Subsequently, I read a meta post about what to do in such situations. But since my question was cached by SO, I will post it anyway. Maybe someone has the same โ€œproblemโ€ in the future. I will send an answer if no one does.

+4
source share
4 answers

If you use Eclipse Collections , you can convert both lists to Bags and just use equals () between Bags. The contract of Bag.equals() is that two Bags are equal if they have the same quantity of each item, but the order is not taken into account. There is also a performance advantage. toBag() and Bag.equals() are each O (n), so this method is faster than sorting lists.

 Assert.assertEquals( Lists.mutable.with(1, 2, 3, 1).toBag(), Lists.mutable.with(3, 2, 1, 1).toBag()); 

Note: I am a committer for Eclipse collections.

+2
source

If you have no objection to adding third-party libraries, you can use CollectionUtils.isEqualCollection(java.util.Collection a, java.util.Collection b) from Apache Commons-Lang. It essentially compares two arbitrary collections (also lists), ignoring the order of the elements.

From the API documentation:

Returns true if the collection data contains exactly the same elements with exactly the same power. That is, if the power of e in is equal to the power of e in b, for each element e in or b.

+2
source

I can come up with several ways to do this, including iterating over the list and using list.contains , as Sotirios mentions in his comment. Another would be to use (new HashSet(list1)).equals(new HashSet(list2)) (both of these solutions could discard duplicate entries).

Another way that involves testing for equivalence of duplicate entries would be to use Collections.sort() to sort the copies of both lists, and then .equals() for comparison. There are many sound ways to do this, probably much more than what I mentioned here.

+1
source

Since there are already answers. I am going to publish mine.

Finally I used java.util.List.containsAll(Collection<?>) . I came across this method, so I did not want to post this question.

@jarnbjo I didnโ€™t understand that there is a dimension of power that you can consider!

EDIT

Added sth. to fix power problems.

  Collection<Object> a, b; boolean equal = (a.size() == b.size()) && a.containsAll(b); 

But that too may fail. If collection a has element x twice, and collection b has element y twice. Then the size is the same, and containsAll() gives true .

0
source

Source: https://habr.com/ru/post/1499438/


All Articles