Java ArrayList - how can I tell if two lists are equal, order not mattering?
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}
I have two ArrayList
s of type Answer
(self-made class).
I'd like to compare the two lists to see if they contain the same contents, but without order mattering.
Example:
//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}
List.equals
states that two lists are equal if they contain the same size, contents, and order of elements. I want the same thing, but without order mattering.
Is there a simple way to do this? Or will I need to do a nested for loop, and manually check each index of both lists?
Note: I can't change them from ArrayList
to another type of list, they need to remain that.
java arraylist
add a comment |
I have two ArrayList
s of type Answer
(self-made class).
I'd like to compare the two lists to see if they contain the same contents, but without order mattering.
Example:
//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}
List.equals
states that two lists are equal if they contain the same size, contents, and order of elements. I want the same thing, but without order mattering.
Is there a simple way to do this? Or will I need to do a nested for loop, and manually check each index of both lists?
Note: I can't change them from ArrayList
to another type of list, they need to remain that.
java arraylist
4
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05
add a comment |
I have two ArrayList
s of type Answer
(self-made class).
I'd like to compare the two lists to see if they contain the same contents, but without order mattering.
Example:
//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}
List.equals
states that two lists are equal if they contain the same size, contents, and order of elements. I want the same thing, but without order mattering.
Is there a simple way to do this? Or will I need to do a nested for loop, and manually check each index of both lists?
Note: I can't change them from ArrayList
to another type of list, they need to remain that.
java arraylist
I have two ArrayList
s of type Answer
(self-made class).
I'd like to compare the two lists to see if they contain the same contents, but without order mattering.
Example:
//These should be equal.
ArrayList<String> listA = {"a", "b", "c"}
ArrayList<String> listB = {"b", "c", "a"}
List.equals
states that two lists are equal if they contain the same size, contents, and order of elements. I want the same thing, but without order mattering.
Is there a simple way to do this? Or will I need to do a nested for loop, and manually check each index of both lists?
Note: I can't change them from ArrayList
to another type of list, they need to remain that.
java arraylist
java arraylist
edited Jan 4 at 16:55


LAD
2,09741026
2,09741026
asked Nov 21 '12 at 20:01
iaacpiaacp
2,08772636
2,08772636
4
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05
add a comment |
4
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05
4
4
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05
add a comment |
17 Answers
17
active
oldest
votes
You could sort both lists using Collections.sort()
and then use the equals method. A slighly better solution is to first check if they are the same length before ordering, if they are not, then they are not equal, then sort, then use equals. For example if you had two lists of Strings it would be something like:
public boolean equalLists(List<String> one, List<String> two){
if (one == null && two == null){
return true;
}
if((one == null && two != null)
|| one != null && two == null
|| one.size() != two.size()){
return false;
}
//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one);
two = new ArrayList<String>(two);
Collections.sort(one);
Collections.sort(two);
return one.equals(two);
}
18
Just remember not to destroy the order of the original list (asCollections.sort
does) - i.e. pass a copy.
– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
You could just addone = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.
– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
Second "if" statement inside function can be simplified asif(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null
– Hugo
Dec 28 '16 at 10:13
|
show 11 more comments
Probably the easiest way for any list would be:
listA.containsAll(listB) && listB.containsAll(listA)
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
Depends on whether[a, b, c]
and[c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.
– yshavit
Nov 21 '12 at 20:48
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
|
show 5 more comments
Apache Commons Collections to the rescue once again:
List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true
List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false
Docs:
org.apache.commons.collections4.CollectionUtils
public static boolean isEqualCollection(java.util.Collection a,
java.util.Collection b)
Returnstrue
iff the givenCollection
s contain exactly the same
elements with exactly the same cardinalities.
That is, iff the
cardinality of e in a is equal to the cardinality of e in b, for each
element e in a or b.
Parameters:
a
- the first collection, must not benull
b
- the second
collection, must not benull
Returns:
true
iff the collections contain
the same elements with the same cardinalities.
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer isfalse
? See my answer.
– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
add a comment |
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
public int count = 0;
}
public boolean haveSameElements(final List<String> list1, final List<String> list2) {
// (list1, list1) is always true
if (list1 == list2) return true;
// If either list is null, or the lengths are not equal, they can't possibly match
if (list1 == null || list2 == null || list1.size() != list2.size())
return false;
// (switch the two checks above if (null, null) should return false)
Map<String, Count> counts = new HashMap<>();
// Count the items in list1
for (String item : list1) {
if (!counts.containsKey(item)) counts.put(item, new Count());
counts.get(item).count += 1;
}
// Subtract the count of items in list2
for (String item : list2) {
// If the map doesn't contain the item here, then this item wasn't in list1
if (!counts.containsKey(item)) return false;
counts.get(item).count -= 1;
}
// If any count is nonzero at this point, then the two lists don't match
for (Map.Entry<String, Count> entry : counts.entrySet()) {
if (entry.getValue().count != 0) return false;
}
return true;
}
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
add a comment |
This is based on @cHao solution. I included several fixes and performance improvements. This runs roughly twice as fast the equals-ordered-copy solution. Works for any collection type. Empty collections and null are regarded as equal. Use to your advantage ;)
/**
* Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
* <p>
* Empty collections and {@code null} are regarded as equal.
*/
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
if (col1 == col2)
return true;
// If either list is null, return whether the other is empty
if (col1 == null)
return col2.isEmpty();
if (col2 == null)
return col1.isEmpty();
// If lengths are not equal, they can't possibly match
if (col1.size() != col2.size())
return false;
// Helper class, so we don't have to do a whole lot of autoboxing
class Count
{
// Initialize as 1, as we would increment it anyway
public int count = 1;
}
final Map<T, Count> counts = new HashMap<>();
// Count the items in list1
for (final T item : col1) {
final Count count = counts.get(item);
if (count != null)
count.count++;
else
// If the map doesn't contain the item, put a new count
counts.put(item, new Count());
}
// Subtract the count of items in list2
for (final T item : col2) {
final Count count = counts.get(item);
// If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal
if (count == null || count.count == 0)
return false;
count.count--;
}
// If any count is nonzero at this point, then the two lists don't match
for (final Count count : counts.values())
if (count.count != 0)
return false;
return true;
}
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
add a comment |
If the cardinality of items doesn't matter (meaning: repeated elements are considered as one), then there is a way to do this without having to sort:
boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));
This will create a Set
out of each List
, and then use HashSet
's equals
method which (of course) disregards ordering.
If cardinality matters, then you must confine yourself to facilities provided by List
; @jschoen's answer would be more fitting in that case.
add a comment |
Think how you would do this yourself, absent a computer or programming language. I give you two lists of elements, and you have to tell me if they contain the same elements. How would you do it?
One approach, as mentioned above, is to sort the lists and then go element-by-element to see if they're equal (which is what List.equals
does). This means either you're allowed to modify the lists or you're allowed to copy them -- and without knowing the assignment, I can't know if either/both of those are allowed.
Another approach would be to go through each list, counting how many times each element appears. If both lists have the same counts at the end, they have the same elements. The code for that would be to translate each list to a map of elem -> (# of times the elem appears in the list)
and then call equals
on the two maps. If the maps are HashMap
, each of those translations is an O(N) operation, as is the comparison. That's going to give you a pretty efficient algorithm in terms of time, at the cost of some extra memory.
add a comment |
I had this same problem and came up with a different solution. This one also works when duplicates are involved:
public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
if(fst != null && snd != null){
if(fst.size() == snd.size()){
// create copied lists so the original list is not modified
List<?> cfst = new ArrayList<Object>(fst);
List<?> csnd = new ArrayList<Object>(snd);
Iterator<?> ifst = cfst.iterator();
boolean foundEqualObject;
while( ifst.hasNext() ){
Iterator<?> isnd = csnd.iterator();
foundEqualObject = false;
while( isnd.hasNext() ){
if( ifst.next().equals(isnd.next()) ){
ifst.remove();
isnd.remove();
foundEqualObject = true;
break;
}
}
if( !foundEqualObject ){
// fail early
break;
}
}
if(cfst.isEmpty()){ //both temporary lists have the same size
return true;
}
}
}else if( fst == null && snd == null ){
return true;
}
return false;
}
Advantages compared to some other solutions:
- less than O(N²) complexity (although I have not tested it's real performance comparing to solutions in other answers here);
- exits early;
- checks for null;
- works even when duplicates are involved: if you have an array
[1,2,3,3]
and another array[1,2,2,3]
most solutions here tell you they are the same when not considering the order. This solution avoids this by removing equal elements from the temporary lists; - uses semantic equality (
equals
) and not reference equality (==
); - does not sort itens, so they don't need to be sortable (by
implement Comparable
) for this solution to work.
add a comment |
I'd say these answers miss a trick.
Bloch, in his essential, wonderful, concise Effective Java, says, in item 47, title "Know and use the libraries", "To summarize, don't reinvent the wheel". And he gives several very clear reasons why not.
There are a few answers here which suggest methods from CollectionUtils
in the Apache Commons Collections library but none has spotted the most beautiful, elegant way of answering this question:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... then in most cases you will ardently wish to do something to these culprits:
// at the very least, name-and-shame them.
}
Culprits: i.e. the elements which are not common to both Lists
. Determining which culprits belong to list1
and which to list2
is relatively straightforward using CollectionUtils.intersection( list1, culprits )
and CollectionUtils.intersection( list2, culprits )
.
However it tends to fall apart in cases like { "a", "a", "b" } disjunction
with { "a", "b", "b" } ... except this is not a failing of the software, but inherent to the nature of the subtleties/ambiguities of the desired task.
NB I was at first disappointed that none of the CollectionUtils
methods provides an overloaded version enabling you to impose your own Comparator
(so you can redefine equals
to suit your purposes).
But from collections4 4.0 there is a new class, Equator
which "determines equality between objects of type T". On examination of the source code of collections4 CollectionUtils.java they seem to be using this with some methods, but as far as I can make out this is not applicable to the methods at the top of the file, using the CardinalityHelper
class... which include disjunction
and intersection
.
I surmise that the Apache people haven't got around to this yet because it is non-trivial: you would have to create something like an "AbstractEquatingCollection" class, which instead of using its elements' inherent equals
and hashCode
methods would instead have to use those of Equator
for all the basic methods, such as add
, contains
, etc. NB in fact when you look at the source code, AbstractCollection
does not implement add
, nor do its abstract subclasses such as AbstractSet
... you have to wait till the concrete classes such as HashSet
and ArrayList
before add
is implemented. Quite a headache.
In the mean time watch this space, I suppose. The obvious interim solution would be to wrap all your elements in a bespoke wrapper class which uses equals
and hashCode
to implement the kind of equality you want... then manipulate Collections
of these wrapper objects.
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
add a comment |
Converting the lists to Guava's Multiset works very well. They are compared regardless of their order and duplicate elements are taken into account as well.
static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}
assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));
add a comment |
Solution which leverages CollectionUtils subtract method:
import static org.apache.commons.collections15.CollectionUtils.subtract;
public class CollectionUtils {
static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
if (a == null && b == null)
return true;
if (a == null || b == null || a.size() != b.size())
return false;
return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
}
}
add a comment |
If you don't hope to sort the collections and you need the result that ["A" "B" "C"] is not equals to ["B" "B" "A" "C"],
l1.containsAll(l2)&&l2.containsAll(l1)
is not enough, you propably need to check the size too :
List<String> l1 =Arrays.asList("A","A","B","C");
List<String> l2 =Arrays.asList("A","B","C");
List<String> l3 =Arrays.asList("A","B","C");
System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected
System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected
public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}
add a comment |
If you care about order, then just use the equals method:
list1.equals(list2)
If you don't care order then use this
Collections.sort(list1);
Collections.sort(list2);
list1.equals(list2)
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
add a comment |
Best of both worlds [@DiddiZ, @Chalkos]: this one mainly builds upon @Chalkos method, but fixes a bug (ifst.next()), and improves initial checks (taken from @DiddiZ) as well as removes the need to copy the first collection (just removes items from a copy of the second collection).
Not requiring a hashing function or sorting, and enabling an early exist on un-equality, this is the most efficient implementation yet. That is unless you have a collection length in the thousands or more, and a very simple hashing function.
public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
if (one == two)
return true;
// If either list is null, return whether the other is empty
if (one == null)
return two.isEmpty();
if (two == null)
return one.isEmpty();
// If lengths are not equal, they can't possibly match
if (one.size() != two.size())
return false;
// copy the second list, so it can be modified
final List<T> ctwo = new ArrayList<>(two);
for (T itm : one) {
Iterator<T> it = ctwo.iterator();
boolean gotEq = false;
while (it.hasNext()) {
if (itm.equals(it.next())) {
it.remove();
gotEq = true;
break;
}
}
if (!gotEq) return false;
}
// All elements in one were found in two, and they're the same size.
return true;
}
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
add a comment |
It is an alternative way to check equality of array lists which can contain null values:
List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);
System.out.println(checkEquality(listA, listB)); // will return TRUE
private List<String> getSortedArrayList(List<String> arrayList)
{
String array = arrayList.toArray(new String[arrayList.size()]);
Arrays.sort(array, new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1 == null && o2 == null)
{
return 0;
}
if (o1 == null)
{
return 1;
}
if (o2 == null)
{
return -1;
}
return o1.compareTo(o2);
}
});
return new ArrayList(Arrays.asList(array));
}
private Boolean checkEquality(List<String> listA, List<String> listB)
{
listA = getSortedArrayList(listA);
listB = getSortedArrayList(listB);
String arrayA = listA.toArray(new String[listA.size()]);
String arrayB = listB.toArray(new String[listB.size()]);
return Arrays.deepEquals(arrayA, arrayB);
}
add a comment |
My solution for this. It is not so cool, but works well.
public static boolean isEqualCollection(List<?> a, List<?> b) {
if (a == null || b == null) {
throw new NullPointerException("The list a and b must be not null.");
}
if (a.size() != b.size()) {
return false;
}
List<?> bCopy = new ArrayList<Object>(b);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < bCopy.size(); j++) {
if (a.get(i).equals(bCopy.get(j))) {
bCopy.remove(j);
break;
}
}
}
return bCopy.isEmpty();
}
add a comment |
In that case lists {"a", "b"} and {"b","a"} are equal. And {"a", "b"} and {"b","a","c"} are not equal. If you use list of complex objects, remember to override equals method, as containsAll uses it inside.
if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
areEqual = true;
}
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code forAbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking aboutLists
, not aboutSets
. Please see my answer.
– mike rodent
Dec 12 '16 at 21:07
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f13501142%2fjava-arraylist-how-can-i-tell-if-two-lists-are-equal-order-not-mattering%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
17 Answers
17
active
oldest
votes
17 Answers
17
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could sort both lists using Collections.sort()
and then use the equals method. A slighly better solution is to first check if they are the same length before ordering, if they are not, then they are not equal, then sort, then use equals. For example if you had two lists of Strings it would be something like:
public boolean equalLists(List<String> one, List<String> two){
if (one == null && two == null){
return true;
}
if((one == null && two != null)
|| one != null && two == null
|| one.size() != two.size()){
return false;
}
//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one);
two = new ArrayList<String>(two);
Collections.sort(one);
Collections.sort(two);
return one.equals(two);
}
18
Just remember not to destroy the order of the original list (asCollections.sort
does) - i.e. pass a copy.
– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
You could just addone = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.
– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
Second "if" statement inside function can be simplified asif(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null
– Hugo
Dec 28 '16 at 10:13
|
show 11 more comments
You could sort both lists using Collections.sort()
and then use the equals method. A slighly better solution is to first check if they are the same length before ordering, if they are not, then they are not equal, then sort, then use equals. For example if you had two lists of Strings it would be something like:
public boolean equalLists(List<String> one, List<String> two){
if (one == null && two == null){
return true;
}
if((one == null && two != null)
|| one != null && two == null
|| one.size() != two.size()){
return false;
}
//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one);
two = new ArrayList<String>(two);
Collections.sort(one);
Collections.sort(two);
return one.equals(two);
}
18
Just remember not to destroy the order of the original list (asCollections.sort
does) - i.e. pass a copy.
– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
You could just addone = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.
– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
Second "if" statement inside function can be simplified asif(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null
– Hugo
Dec 28 '16 at 10:13
|
show 11 more comments
You could sort both lists using Collections.sort()
and then use the equals method. A slighly better solution is to first check if they are the same length before ordering, if they are not, then they are not equal, then sort, then use equals. For example if you had two lists of Strings it would be something like:
public boolean equalLists(List<String> one, List<String> two){
if (one == null && two == null){
return true;
}
if((one == null && two != null)
|| one != null && two == null
|| one.size() != two.size()){
return false;
}
//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one);
two = new ArrayList<String>(two);
Collections.sort(one);
Collections.sort(two);
return one.equals(two);
}
You could sort both lists using Collections.sort()
and then use the equals method. A slighly better solution is to first check if they are the same length before ordering, if they are not, then they are not equal, then sort, then use equals. For example if you had two lists of Strings it would be something like:
public boolean equalLists(List<String> one, List<String> two){
if (one == null && two == null){
return true;
}
if((one == null && two != null)
|| one != null && two == null
|| one.size() != two.size()){
return false;
}
//to avoid messing the order of the lists we will use a copy
//as noted in comments by A. R. S.
one = new ArrayList<String>(one);
two = new ArrayList<String>(two);
Collections.sort(one);
Collections.sort(two);
return one.equals(two);
}
edited Nov 21 '12 at 20:30
answered Nov 21 '12 at 20:06
Jacob SchoenJacob Schoen
10k156796
10k156796
18
Just remember not to destroy the order of the original list (asCollections.sort
does) - i.e. pass a copy.
– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
You could just addone = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.
– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
Second "if" statement inside function can be simplified asif(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null
– Hugo
Dec 28 '16 at 10:13
|
show 11 more comments
18
Just remember not to destroy the order of the original list (asCollections.sort
does) - i.e. pass a copy.
– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
You could just addone = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.
– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
Second "if" statement inside function can be simplified asif(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null
– Hugo
Dec 28 '16 at 10:13
18
18
Just remember not to destroy the order of the original list (as
Collections.sort
does) - i.e. pass a copy.– arshajii
Nov 21 '12 at 20:10
Just remember not to destroy the order of the original list (as
Collections.sort
does) - i.e. pass a copy.– arshajii
Nov 21 '12 at 20:10
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
@A.R.S. yes that is a definite side effect, but only if it matters in their particular case.
– Jacob Schoen
Nov 21 '12 at 20:11
3
3
You could just add
one = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.– arshajii
Nov 21 '12 at 20:14
You could just add
one = new ArrayList<String>(one); two = new ArrayList<String>(two);
to avoid ruining the arguments.– arshajii
Nov 21 '12 at 20:14
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
Added in, as in is probably a good idea. Thanks
– Jacob Schoen
Nov 21 '12 at 20:18
2
2
Second "if" statement inside function can be simplified as
if(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null– Hugo
Dec 28 '16 at 10:13
Second "if" statement inside function can be simplified as
if(one == null || two == null || one.size() != two.size()){ return false; }
because you are already checking if both one and two are null– Hugo
Dec 28 '16 at 10:13
|
show 11 more comments
Probably the easiest way for any list would be:
listA.containsAll(listB) && listB.containsAll(listA)
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
Depends on whether[a, b, c]
and[c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.
– yshavit
Nov 21 '12 at 20:48
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
|
show 5 more comments
Probably the easiest way for any list would be:
listA.containsAll(listB) && listB.containsAll(listA)
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
Depends on whether[a, b, c]
and[c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.
– yshavit
Nov 21 '12 at 20:48
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
|
show 5 more comments
Probably the easiest way for any list would be:
listA.containsAll(listB) && listB.containsAll(listA)
Probably the easiest way for any list would be:
listA.containsAll(listB) && listB.containsAll(listA)
answered Nov 21 '12 at 20:33
user381105
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
Depends on whether[a, b, c]
and[c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.
– yshavit
Nov 21 '12 at 20:48
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
|
show 5 more comments
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
Depends on whether[a, b, c]
and[c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.
– yshavit
Nov 21 '12 at 20:48
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
3
3
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
Where is the fun in that. In all seriousness though this is probably the better solution.
– Jacob Schoen
Nov 21 '12 at 20:37
56
56
Depends on whether
[a, b, c]
and [c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.– yshavit
Nov 21 '12 at 20:48
Depends on whether
[a, b, c]
and [c, b, a, b]
are considered to have the same contents. This answer would say they do, but it could be that for the OP they don't (since one contains a duplicate and the other doesn't). To say nothing of the efficiency issues.– yshavit
Nov 21 '12 at 20:48
4
4
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
enhancing based on comments - System.out.println(((l1.size() == l2.size())&&l2.containsAll(l1)&&l1.containsAll(l2)));
– Nrj
Apr 7 '15 at 9:19
6
6
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
@Nrj , what about [1,2,2] and [2,1,1]?
– ROMANIA_engineer
Jul 24 '15 at 18:47
2
2
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
This approach has complexity of O(n^2). Consider two list which are in reverse order, for ex: [1,2,3] and [3,2,1]. For first element it will have to scan n elements, for second n-1 elements and so on. So complexity will be of order n^2. I think better way will be to sort and then use equals. It will have complexity of O(n * log(n))
– puneet
Oct 15 '15 at 9:28
|
show 5 more comments
Apache Commons Collections to the rescue once again:
List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true
List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false
Docs:
org.apache.commons.collections4.CollectionUtils
public static boolean isEqualCollection(java.util.Collection a,
java.util.Collection b)
Returnstrue
iff the givenCollection
s contain exactly the same
elements with exactly the same cardinalities.
That is, iff the
cardinality of e in a is equal to the cardinality of e in b, for each
element e in a or b.
Parameters:
a
- the first collection, must not benull
b
- the second
collection, must not benull
Returns:
true
iff the collections contain
the same elements with the same cardinalities.
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer isfalse
? See my answer.
– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
add a comment |
Apache Commons Collections to the rescue once again:
List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true
List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false
Docs:
org.apache.commons.collections4.CollectionUtils
public static boolean isEqualCollection(java.util.Collection a,
java.util.Collection b)
Returnstrue
iff the givenCollection
s contain exactly the same
elements with exactly the same cardinalities.
That is, iff the
cardinality of e in a is equal to the cardinality of e in b, for each
element e in a or b.
Parameters:
a
- the first collection, must not benull
b
- the second
collection, must not benull
Returns:
true
iff the collections contain
the same elements with the same cardinalities.
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer isfalse
? See my answer.
– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
add a comment |
Apache Commons Collections to the rescue once again:
List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true
List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false
Docs:
org.apache.commons.collections4.CollectionUtils
public static boolean isEqualCollection(java.util.Collection a,
java.util.Collection b)
Returnstrue
iff the givenCollection
s contain exactly the same
elements with exactly the same cardinalities.
That is, iff the
cardinality of e in a is equal to the cardinality of e in b, for each
element e in a or b.
Parameters:
a
- the first collection, must not benull
b
- the second
collection, must not benull
Returns:
true
iff the collections contain
the same elements with the same cardinalities.
Apache Commons Collections to the rescue once again:
List<String> listA = Arrays.asList("a", "b", "b", "c");
List<String> listB = Arrays.asList("b", "c", "a", "b");
System.out.println(CollectionUtils.isEqualCollection(listA, listB)); // true
List<String> listC = Arrays.asList("a", "b", "c");
List<String> listD = Arrays.asList("a", "b", "c", "c");
System.out.println(CollectionUtils.isEqualCollection(listC, listD)); // false
Docs:
org.apache.commons.collections4.CollectionUtils
public static boolean isEqualCollection(java.util.Collection a,
java.util.Collection b)
Returnstrue
iff the givenCollection
s contain exactly the same
elements with exactly the same cardinalities.
That is, iff the
cardinality of e in a is equal to the cardinality of e in b, for each
element e in a or b.
Parameters:
a
- the first collection, must not benull
b
- the second
collection, must not benull
Returns:
true
iff the collections contain
the same elements with the same cardinalities.
edited Feb 16 '16 at 18:36
ArtB
10.2k2093135
10.2k2093135
answered Mar 24 '14 at 19:53


acdcjunioracdcjunior
82.9k22195194
82.9k22195194
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer isfalse
? See my answer.
– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
add a comment |
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer isfalse
? See my answer.
– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
4
4
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
If only they handle null cases as well...
– Tony Lang
Oct 31 '14 at 14:23
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
The implementation seems more or less similar with DiddiZ's answer.
– user227353
Aug 27 '15 at 16:48
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer is
false
? See my answer.– mike rodent
Dec 12 '16 at 21:16
OK... but what about getting hold of the culprits (elements which are not common to the two lists) if the answer is
false
? See my answer.– mike rodent
Dec 12 '16 at 21:16
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
Thanks, that's working like a charm for me!
– eugene.polschikov
Jun 13 '18 at 17:06
add a comment |
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
public int count = 0;
}
public boolean haveSameElements(final List<String> list1, final List<String> list2) {
// (list1, list1) is always true
if (list1 == list2) return true;
// If either list is null, or the lengths are not equal, they can't possibly match
if (list1 == null || list2 == null || list1.size() != list2.size())
return false;
// (switch the two checks above if (null, null) should return false)
Map<String, Count> counts = new HashMap<>();
// Count the items in list1
for (String item : list1) {
if (!counts.containsKey(item)) counts.put(item, new Count());
counts.get(item).count += 1;
}
// Subtract the count of items in list2
for (String item : list2) {
// If the map doesn't contain the item here, then this item wasn't in list1
if (!counts.containsKey(item)) return false;
counts.get(item).count -= 1;
}
// If any count is nonzero at this point, then the two lists don't match
for (Map.Entry<String, Count> entry : counts.entrySet()) {
if (entry.getValue().count != 0) return false;
}
return true;
}
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
add a comment |
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
public int count = 0;
}
public boolean haveSameElements(final List<String> list1, final List<String> list2) {
// (list1, list1) is always true
if (list1 == list2) return true;
// If either list is null, or the lengths are not equal, they can't possibly match
if (list1 == null || list2 == null || list1.size() != list2.size())
return false;
// (switch the two checks above if (null, null) should return false)
Map<String, Count> counts = new HashMap<>();
// Count the items in list1
for (String item : list1) {
if (!counts.containsKey(item)) counts.put(item, new Count());
counts.get(item).count += 1;
}
// Subtract the count of items in list2
for (String item : list2) {
// If the map doesn't contain the item here, then this item wasn't in list1
if (!counts.containsKey(item)) return false;
counts.get(item).count -= 1;
}
// If any count is nonzero at this point, then the two lists don't match
for (Map.Entry<String, Count> entry : counts.entrySet()) {
if (entry.getValue().count != 0) return false;
}
return true;
}
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
add a comment |
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
public int count = 0;
}
public boolean haveSameElements(final List<String> list1, final List<String> list2) {
// (list1, list1) is always true
if (list1 == list2) return true;
// If either list is null, or the lengths are not equal, they can't possibly match
if (list1 == null || list2 == null || list1.size() != list2.size())
return false;
// (switch the two checks above if (null, null) should return false)
Map<String, Count> counts = new HashMap<>();
// Count the items in list1
for (String item : list1) {
if (!counts.containsKey(item)) counts.put(item, new Count());
counts.get(item).count += 1;
}
// Subtract the count of items in list2
for (String item : list2) {
// If the map doesn't contain the item here, then this item wasn't in list1
if (!counts.containsKey(item)) return false;
counts.get(item).count -= 1;
}
// If any count is nonzero at this point, then the two lists don't match
for (Map.Entry<String, Count> entry : counts.entrySet()) {
if (entry.getValue().count != 0) return false;
}
return true;
}
// helper class, so we don't have to do a whole lot of autoboxing
private static class Count {
public int count = 0;
}
public boolean haveSameElements(final List<String> list1, final List<String> list2) {
// (list1, list1) is always true
if (list1 == list2) return true;
// If either list is null, or the lengths are not equal, they can't possibly match
if (list1 == null || list2 == null || list1.size() != list2.size())
return false;
// (switch the two checks above if (null, null) should return false)
Map<String, Count> counts = new HashMap<>();
// Count the items in list1
for (String item : list1) {
if (!counts.containsKey(item)) counts.put(item, new Count());
counts.get(item).count += 1;
}
// Subtract the count of items in list2
for (String item : list2) {
// If the map doesn't contain the item here, then this item wasn't in list1
if (!counts.containsKey(item)) return false;
counts.get(item).count -= 1;
}
// If any count is nonzero at this point, then the two lists don't match
for (Map.Entry<String, Count> entry : counts.entrySet()) {
if (entry.getValue().count != 0) return false;
}
return true;
}
edited Aug 21 '17 at 6:32
Community♦
11
11
answered Nov 21 '12 at 21:02
cHaocHao
69.3k14116155
69.3k14116155
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
add a comment |
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Wow, was really surprised to find this performing faster than all other solutions. And it supports early-out.
– DiddiZ
Dec 1 '13 at 19:30
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
Different thing.
– RuudVanNistelrooy
Aug 27 '14 at 12:15
add a comment |
This is based on @cHao solution. I included several fixes and performance improvements. This runs roughly twice as fast the equals-ordered-copy solution. Works for any collection type. Empty collections and null are regarded as equal. Use to your advantage ;)
/**
* Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
* <p>
* Empty collections and {@code null} are regarded as equal.
*/
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
if (col1 == col2)
return true;
// If either list is null, return whether the other is empty
if (col1 == null)
return col2.isEmpty();
if (col2 == null)
return col1.isEmpty();
// If lengths are not equal, they can't possibly match
if (col1.size() != col2.size())
return false;
// Helper class, so we don't have to do a whole lot of autoboxing
class Count
{
// Initialize as 1, as we would increment it anyway
public int count = 1;
}
final Map<T, Count> counts = new HashMap<>();
// Count the items in list1
for (final T item : col1) {
final Count count = counts.get(item);
if (count != null)
count.count++;
else
// If the map doesn't contain the item, put a new count
counts.put(item, new Count());
}
// Subtract the count of items in list2
for (final T item : col2) {
final Count count = counts.get(item);
// If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal
if (count == null || count.count == 0)
return false;
count.count--;
}
// If any count is nonzero at this point, then the two lists don't match
for (final Count count : counts.values())
if (count.count != 0)
return false;
return true;
}
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
add a comment |
This is based on @cHao solution. I included several fixes and performance improvements. This runs roughly twice as fast the equals-ordered-copy solution. Works for any collection type. Empty collections and null are regarded as equal. Use to your advantage ;)
/**
* Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
* <p>
* Empty collections and {@code null} are regarded as equal.
*/
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
if (col1 == col2)
return true;
// If either list is null, return whether the other is empty
if (col1 == null)
return col2.isEmpty();
if (col2 == null)
return col1.isEmpty();
// If lengths are not equal, they can't possibly match
if (col1.size() != col2.size())
return false;
// Helper class, so we don't have to do a whole lot of autoboxing
class Count
{
// Initialize as 1, as we would increment it anyway
public int count = 1;
}
final Map<T, Count> counts = new HashMap<>();
// Count the items in list1
for (final T item : col1) {
final Count count = counts.get(item);
if (count != null)
count.count++;
else
// If the map doesn't contain the item, put a new count
counts.put(item, new Count());
}
// Subtract the count of items in list2
for (final T item : col2) {
final Count count = counts.get(item);
// If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal
if (count == null || count.count == 0)
return false;
count.count--;
}
// If any count is nonzero at this point, then the two lists don't match
for (final Count count : counts.values())
if (count.count != 0)
return false;
return true;
}
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
add a comment |
This is based on @cHao solution. I included several fixes and performance improvements. This runs roughly twice as fast the equals-ordered-copy solution. Works for any collection type. Empty collections and null are regarded as equal. Use to your advantage ;)
/**
* Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
* <p>
* Empty collections and {@code null} are regarded as equal.
*/
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
if (col1 == col2)
return true;
// If either list is null, return whether the other is empty
if (col1 == null)
return col2.isEmpty();
if (col2 == null)
return col1.isEmpty();
// If lengths are not equal, they can't possibly match
if (col1.size() != col2.size())
return false;
// Helper class, so we don't have to do a whole lot of autoboxing
class Count
{
// Initialize as 1, as we would increment it anyway
public int count = 1;
}
final Map<T, Count> counts = new HashMap<>();
// Count the items in list1
for (final T item : col1) {
final Count count = counts.get(item);
if (count != null)
count.count++;
else
// If the map doesn't contain the item, put a new count
counts.put(item, new Count());
}
// Subtract the count of items in list2
for (final T item : col2) {
final Count count = counts.get(item);
// If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal
if (count == null || count.count == 0)
return false;
count.count--;
}
// If any count is nonzero at this point, then the two lists don't match
for (final Count count : counts.values())
if (count.count != 0)
return false;
return true;
}
This is based on @cHao solution. I included several fixes and performance improvements. This runs roughly twice as fast the equals-ordered-copy solution. Works for any collection type. Empty collections and null are regarded as equal. Use to your advantage ;)
/**
* Returns if both {@link Collection Collections} contains the same elements, in the same quantities, regardless of order and collection type.
* <p>
* Empty collections and {@code null} are regarded as equal.
*/
public static <T> boolean haveSameElements(Collection<T> col1, Collection<T> col2) {
if (col1 == col2)
return true;
// If either list is null, return whether the other is empty
if (col1 == null)
return col2.isEmpty();
if (col2 == null)
return col1.isEmpty();
// If lengths are not equal, they can't possibly match
if (col1.size() != col2.size())
return false;
// Helper class, so we don't have to do a whole lot of autoboxing
class Count
{
// Initialize as 1, as we would increment it anyway
public int count = 1;
}
final Map<T, Count> counts = new HashMap<>();
// Count the items in list1
for (final T item : col1) {
final Count count = counts.get(item);
if (count != null)
count.count++;
else
// If the map doesn't contain the item, put a new count
counts.put(item, new Count());
}
// Subtract the count of items in list2
for (final T item : col2) {
final Count count = counts.get(item);
// If the map doesn't contain the item, or the count is already reduced to 0, the lists are unequal
if (count == null || count.count == 0)
return false;
count.count--;
}
// If any count is nonzero at this point, then the two lists don't match
for (final Count count : counts.values())
if (count.count != 0)
return false;
return true;
}
edited Feb 2 '14 at 14:56
answered Dec 1 '13 at 20:31
DiddiZDiddiZ
418517
418517
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
add a comment |
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
You can skip the final for-loop using a sum counter. The sum counter will count the total of counts at each stage. Increase the sum counter in the first for-loop, and decrease it in the second for-loop. If the sum counter is greater than 0, the lists don't match, otherwise they do. Currently, in the final for-loop you check if all counts are zero or in other words, if the sum of all counts is zero. Using the sum counter kind of reverses this check, returning true if the total of counts is zero, or false otherwise.
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
IMO, it is worth skipping that for-loop since when the lists do match (worst-case scenario) the for-loop adds another unnecessary O(n).
– SatA
Jun 1 '16 at 15:42
add a comment |
If the cardinality of items doesn't matter (meaning: repeated elements are considered as one), then there is a way to do this without having to sort:
boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));
This will create a Set
out of each List
, and then use HashSet
's equals
method which (of course) disregards ordering.
If cardinality matters, then you must confine yourself to facilities provided by List
; @jschoen's answer would be more fitting in that case.
add a comment |
If the cardinality of items doesn't matter (meaning: repeated elements are considered as one), then there is a way to do this without having to sort:
boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));
This will create a Set
out of each List
, and then use HashSet
's equals
method which (of course) disregards ordering.
If cardinality matters, then you must confine yourself to facilities provided by List
; @jschoen's answer would be more fitting in that case.
add a comment |
If the cardinality of items doesn't matter (meaning: repeated elements are considered as one), then there is a way to do this without having to sort:
boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));
This will create a Set
out of each List
, and then use HashSet
's equals
method which (of course) disregards ordering.
If cardinality matters, then you must confine yourself to facilities provided by List
; @jschoen's answer would be more fitting in that case.
If the cardinality of items doesn't matter (meaning: repeated elements are considered as one), then there is a way to do this without having to sort:
boolean result = new HashSet<>(listA).equals(new HashSet<>(listB));
This will create a Set
out of each List
, and then use HashSet
's equals
method which (of course) disregards ordering.
If cardinality matters, then you must confine yourself to facilities provided by List
; @jschoen's answer would be more fitting in that case.
edited Jun 6 '18 at 0:40
shmosel
37.1k43996
37.1k43996
answered Nov 21 '12 at 20:33
IsaacIsaac
14k34172
14k34172
add a comment |
add a comment |
Think how you would do this yourself, absent a computer or programming language. I give you two lists of elements, and you have to tell me if they contain the same elements. How would you do it?
One approach, as mentioned above, is to sort the lists and then go element-by-element to see if they're equal (which is what List.equals
does). This means either you're allowed to modify the lists or you're allowed to copy them -- and without knowing the assignment, I can't know if either/both of those are allowed.
Another approach would be to go through each list, counting how many times each element appears. If both lists have the same counts at the end, they have the same elements. The code for that would be to translate each list to a map of elem -> (# of times the elem appears in the list)
and then call equals
on the two maps. If the maps are HashMap
, each of those translations is an O(N) operation, as is the comparison. That's going to give you a pretty efficient algorithm in terms of time, at the cost of some extra memory.
add a comment |
Think how you would do this yourself, absent a computer or programming language. I give you two lists of elements, and you have to tell me if they contain the same elements. How would you do it?
One approach, as mentioned above, is to sort the lists and then go element-by-element to see if they're equal (which is what List.equals
does). This means either you're allowed to modify the lists or you're allowed to copy them -- and without knowing the assignment, I can't know if either/both of those are allowed.
Another approach would be to go through each list, counting how many times each element appears. If both lists have the same counts at the end, they have the same elements. The code for that would be to translate each list to a map of elem -> (# of times the elem appears in the list)
and then call equals
on the two maps. If the maps are HashMap
, each of those translations is an O(N) operation, as is the comparison. That's going to give you a pretty efficient algorithm in terms of time, at the cost of some extra memory.
add a comment |
Think how you would do this yourself, absent a computer or programming language. I give you two lists of elements, and you have to tell me if they contain the same elements. How would you do it?
One approach, as mentioned above, is to sort the lists and then go element-by-element to see if they're equal (which is what List.equals
does). This means either you're allowed to modify the lists or you're allowed to copy them -- and without knowing the assignment, I can't know if either/both of those are allowed.
Another approach would be to go through each list, counting how many times each element appears. If both lists have the same counts at the end, they have the same elements. The code for that would be to translate each list to a map of elem -> (# of times the elem appears in the list)
and then call equals
on the two maps. If the maps are HashMap
, each of those translations is an O(N) operation, as is the comparison. That's going to give you a pretty efficient algorithm in terms of time, at the cost of some extra memory.
Think how you would do this yourself, absent a computer or programming language. I give you two lists of elements, and you have to tell me if they contain the same elements. How would you do it?
One approach, as mentioned above, is to sort the lists and then go element-by-element to see if they're equal (which is what List.equals
does). This means either you're allowed to modify the lists or you're allowed to copy them -- and without knowing the assignment, I can't know if either/both of those are allowed.
Another approach would be to go through each list, counting how many times each element appears. If both lists have the same counts at the end, they have the same elements. The code for that would be to translate each list to a map of elem -> (# of times the elem appears in the list)
and then call equals
on the two maps. If the maps are HashMap
, each of those translations is an O(N) operation, as is the comparison. That's going to give you a pretty efficient algorithm in terms of time, at the cost of some extra memory.
edited Nov 21 '12 at 23:16
answered Nov 21 '12 at 20:22


yshavityshavit
35.6k66599
35.6k66599
add a comment |
add a comment |
I had this same problem and came up with a different solution. This one also works when duplicates are involved:
public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
if(fst != null && snd != null){
if(fst.size() == snd.size()){
// create copied lists so the original list is not modified
List<?> cfst = new ArrayList<Object>(fst);
List<?> csnd = new ArrayList<Object>(snd);
Iterator<?> ifst = cfst.iterator();
boolean foundEqualObject;
while( ifst.hasNext() ){
Iterator<?> isnd = csnd.iterator();
foundEqualObject = false;
while( isnd.hasNext() ){
if( ifst.next().equals(isnd.next()) ){
ifst.remove();
isnd.remove();
foundEqualObject = true;
break;
}
}
if( !foundEqualObject ){
// fail early
break;
}
}
if(cfst.isEmpty()){ //both temporary lists have the same size
return true;
}
}
}else if( fst == null && snd == null ){
return true;
}
return false;
}
Advantages compared to some other solutions:
- less than O(N²) complexity (although I have not tested it's real performance comparing to solutions in other answers here);
- exits early;
- checks for null;
- works even when duplicates are involved: if you have an array
[1,2,3,3]
and another array[1,2,2,3]
most solutions here tell you they are the same when not considering the order. This solution avoids this by removing equal elements from the temporary lists; - uses semantic equality (
equals
) and not reference equality (==
); - does not sort itens, so they don't need to be sortable (by
implement Comparable
) for this solution to work.
add a comment |
I had this same problem and came up with a different solution. This one also works when duplicates are involved:
public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
if(fst != null && snd != null){
if(fst.size() == snd.size()){
// create copied lists so the original list is not modified
List<?> cfst = new ArrayList<Object>(fst);
List<?> csnd = new ArrayList<Object>(snd);
Iterator<?> ifst = cfst.iterator();
boolean foundEqualObject;
while( ifst.hasNext() ){
Iterator<?> isnd = csnd.iterator();
foundEqualObject = false;
while( isnd.hasNext() ){
if( ifst.next().equals(isnd.next()) ){
ifst.remove();
isnd.remove();
foundEqualObject = true;
break;
}
}
if( !foundEqualObject ){
// fail early
break;
}
}
if(cfst.isEmpty()){ //both temporary lists have the same size
return true;
}
}
}else if( fst == null && snd == null ){
return true;
}
return false;
}
Advantages compared to some other solutions:
- less than O(N²) complexity (although I have not tested it's real performance comparing to solutions in other answers here);
- exits early;
- checks for null;
- works even when duplicates are involved: if you have an array
[1,2,3,3]
and another array[1,2,2,3]
most solutions here tell you they are the same when not considering the order. This solution avoids this by removing equal elements from the temporary lists; - uses semantic equality (
equals
) and not reference equality (==
); - does not sort itens, so they don't need to be sortable (by
implement Comparable
) for this solution to work.
add a comment |
I had this same problem and came up with a different solution. This one also works when duplicates are involved:
public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
if(fst != null && snd != null){
if(fst.size() == snd.size()){
// create copied lists so the original list is not modified
List<?> cfst = new ArrayList<Object>(fst);
List<?> csnd = new ArrayList<Object>(snd);
Iterator<?> ifst = cfst.iterator();
boolean foundEqualObject;
while( ifst.hasNext() ){
Iterator<?> isnd = csnd.iterator();
foundEqualObject = false;
while( isnd.hasNext() ){
if( ifst.next().equals(isnd.next()) ){
ifst.remove();
isnd.remove();
foundEqualObject = true;
break;
}
}
if( !foundEqualObject ){
// fail early
break;
}
}
if(cfst.isEmpty()){ //both temporary lists have the same size
return true;
}
}
}else if( fst == null && snd == null ){
return true;
}
return false;
}
Advantages compared to some other solutions:
- less than O(N²) complexity (although I have not tested it's real performance comparing to solutions in other answers here);
- exits early;
- checks for null;
- works even when duplicates are involved: if you have an array
[1,2,3,3]
and another array[1,2,2,3]
most solutions here tell you they are the same when not considering the order. This solution avoids this by removing equal elements from the temporary lists; - uses semantic equality (
equals
) and not reference equality (==
); - does not sort itens, so they don't need to be sortable (by
implement Comparable
) for this solution to work.
I had this same problem and came up with a different solution. This one also works when duplicates are involved:
public static boolean equalsWithoutOrder(List<?> fst, List<?> snd){
if(fst != null && snd != null){
if(fst.size() == snd.size()){
// create copied lists so the original list is not modified
List<?> cfst = new ArrayList<Object>(fst);
List<?> csnd = new ArrayList<Object>(snd);
Iterator<?> ifst = cfst.iterator();
boolean foundEqualObject;
while( ifst.hasNext() ){
Iterator<?> isnd = csnd.iterator();
foundEqualObject = false;
while( isnd.hasNext() ){
if( ifst.next().equals(isnd.next()) ){
ifst.remove();
isnd.remove();
foundEqualObject = true;
break;
}
}
if( !foundEqualObject ){
// fail early
break;
}
}
if(cfst.isEmpty()){ //both temporary lists have the same size
return true;
}
}
}else if( fst == null && snd == null ){
return true;
}
return false;
}
Advantages compared to some other solutions:
- less than O(N²) complexity (although I have not tested it's real performance comparing to solutions in other answers here);
- exits early;
- checks for null;
- works even when duplicates are involved: if you have an array
[1,2,3,3]
and another array[1,2,2,3]
most solutions here tell you they are the same when not considering the order. This solution avoids this by removing equal elements from the temporary lists; - uses semantic equality (
equals
) and not reference equality (==
); - does not sort itens, so they don't need to be sortable (by
implement Comparable
) for this solution to work.
edited Aug 13 '15 at 0:07
answered Jul 24 '15 at 12:31
ChalkosChalkos
1527
1527
add a comment |
add a comment |
I'd say these answers miss a trick.
Bloch, in his essential, wonderful, concise Effective Java, says, in item 47, title "Know and use the libraries", "To summarize, don't reinvent the wheel". And he gives several very clear reasons why not.
There are a few answers here which suggest methods from CollectionUtils
in the Apache Commons Collections library but none has spotted the most beautiful, elegant way of answering this question:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... then in most cases you will ardently wish to do something to these culprits:
// at the very least, name-and-shame them.
}
Culprits: i.e. the elements which are not common to both Lists
. Determining which culprits belong to list1
and which to list2
is relatively straightforward using CollectionUtils.intersection( list1, culprits )
and CollectionUtils.intersection( list2, culprits )
.
However it tends to fall apart in cases like { "a", "a", "b" } disjunction
with { "a", "b", "b" } ... except this is not a failing of the software, but inherent to the nature of the subtleties/ambiguities of the desired task.
NB I was at first disappointed that none of the CollectionUtils
methods provides an overloaded version enabling you to impose your own Comparator
(so you can redefine equals
to suit your purposes).
But from collections4 4.0 there is a new class, Equator
which "determines equality between objects of type T". On examination of the source code of collections4 CollectionUtils.java they seem to be using this with some methods, but as far as I can make out this is not applicable to the methods at the top of the file, using the CardinalityHelper
class... which include disjunction
and intersection
.
I surmise that the Apache people haven't got around to this yet because it is non-trivial: you would have to create something like an "AbstractEquatingCollection" class, which instead of using its elements' inherent equals
and hashCode
methods would instead have to use those of Equator
for all the basic methods, such as add
, contains
, etc. NB in fact when you look at the source code, AbstractCollection
does not implement add
, nor do its abstract subclasses such as AbstractSet
... you have to wait till the concrete classes such as HashSet
and ArrayList
before add
is implemented. Quite a headache.
In the mean time watch this space, I suppose. The obvious interim solution would be to wrap all your elements in a bespoke wrapper class which uses equals
and hashCode
to implement the kind of equality you want... then manipulate Collections
of these wrapper objects.
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
add a comment |
I'd say these answers miss a trick.
Bloch, in his essential, wonderful, concise Effective Java, says, in item 47, title "Know and use the libraries", "To summarize, don't reinvent the wheel". And he gives several very clear reasons why not.
There are a few answers here which suggest methods from CollectionUtils
in the Apache Commons Collections library but none has spotted the most beautiful, elegant way of answering this question:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... then in most cases you will ardently wish to do something to these culprits:
// at the very least, name-and-shame them.
}
Culprits: i.e. the elements which are not common to both Lists
. Determining which culprits belong to list1
and which to list2
is relatively straightforward using CollectionUtils.intersection( list1, culprits )
and CollectionUtils.intersection( list2, culprits )
.
However it tends to fall apart in cases like { "a", "a", "b" } disjunction
with { "a", "b", "b" } ... except this is not a failing of the software, but inherent to the nature of the subtleties/ambiguities of the desired task.
NB I was at first disappointed that none of the CollectionUtils
methods provides an overloaded version enabling you to impose your own Comparator
(so you can redefine equals
to suit your purposes).
But from collections4 4.0 there is a new class, Equator
which "determines equality between objects of type T". On examination of the source code of collections4 CollectionUtils.java they seem to be using this with some methods, but as far as I can make out this is not applicable to the methods at the top of the file, using the CardinalityHelper
class... which include disjunction
and intersection
.
I surmise that the Apache people haven't got around to this yet because it is non-trivial: you would have to create something like an "AbstractEquatingCollection" class, which instead of using its elements' inherent equals
and hashCode
methods would instead have to use those of Equator
for all the basic methods, such as add
, contains
, etc. NB in fact when you look at the source code, AbstractCollection
does not implement add
, nor do its abstract subclasses such as AbstractSet
... you have to wait till the concrete classes such as HashSet
and ArrayList
before add
is implemented. Quite a headache.
In the mean time watch this space, I suppose. The obvious interim solution would be to wrap all your elements in a bespoke wrapper class which uses equals
and hashCode
to implement the kind of equality you want... then manipulate Collections
of these wrapper objects.
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
add a comment |
I'd say these answers miss a trick.
Bloch, in his essential, wonderful, concise Effective Java, says, in item 47, title "Know and use the libraries", "To summarize, don't reinvent the wheel". And he gives several very clear reasons why not.
There are a few answers here which suggest methods from CollectionUtils
in the Apache Commons Collections library but none has spotted the most beautiful, elegant way of answering this question:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... then in most cases you will ardently wish to do something to these culprits:
// at the very least, name-and-shame them.
}
Culprits: i.e. the elements which are not common to both Lists
. Determining which culprits belong to list1
and which to list2
is relatively straightforward using CollectionUtils.intersection( list1, culprits )
and CollectionUtils.intersection( list2, culprits )
.
However it tends to fall apart in cases like { "a", "a", "b" } disjunction
with { "a", "b", "b" } ... except this is not a failing of the software, but inherent to the nature of the subtleties/ambiguities of the desired task.
NB I was at first disappointed that none of the CollectionUtils
methods provides an overloaded version enabling you to impose your own Comparator
(so you can redefine equals
to suit your purposes).
But from collections4 4.0 there is a new class, Equator
which "determines equality between objects of type T". On examination of the source code of collections4 CollectionUtils.java they seem to be using this with some methods, but as far as I can make out this is not applicable to the methods at the top of the file, using the CardinalityHelper
class... which include disjunction
and intersection
.
I surmise that the Apache people haven't got around to this yet because it is non-trivial: you would have to create something like an "AbstractEquatingCollection" class, which instead of using its elements' inherent equals
and hashCode
methods would instead have to use those of Equator
for all the basic methods, such as add
, contains
, etc. NB in fact when you look at the source code, AbstractCollection
does not implement add
, nor do its abstract subclasses such as AbstractSet
... you have to wait till the concrete classes such as HashSet
and ArrayList
before add
is implemented. Quite a headache.
In the mean time watch this space, I suppose. The obvious interim solution would be to wrap all your elements in a bespoke wrapper class which uses equals
and hashCode
to implement the kind of equality you want... then manipulate Collections
of these wrapper objects.
I'd say these answers miss a trick.
Bloch, in his essential, wonderful, concise Effective Java, says, in item 47, title "Know and use the libraries", "To summarize, don't reinvent the wheel". And he gives several very clear reasons why not.
There are a few answers here which suggest methods from CollectionUtils
in the Apache Commons Collections library but none has spotted the most beautiful, elegant way of answering this question:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... then in most cases you will ardently wish to do something to these culprits:
// at the very least, name-and-shame them.
}
Culprits: i.e. the elements which are not common to both Lists
. Determining which culprits belong to list1
and which to list2
is relatively straightforward using CollectionUtils.intersection( list1, culprits )
and CollectionUtils.intersection( list2, culprits )
.
However it tends to fall apart in cases like { "a", "a", "b" } disjunction
with { "a", "b", "b" } ... except this is not a failing of the software, but inherent to the nature of the subtleties/ambiguities of the desired task.
NB I was at first disappointed that none of the CollectionUtils
methods provides an overloaded version enabling you to impose your own Comparator
(so you can redefine equals
to suit your purposes).
But from collections4 4.0 there is a new class, Equator
which "determines equality between objects of type T". On examination of the source code of collections4 CollectionUtils.java they seem to be using this with some methods, but as far as I can make out this is not applicable to the methods at the top of the file, using the CardinalityHelper
class... which include disjunction
and intersection
.
I surmise that the Apache people haven't got around to this yet because it is non-trivial: you would have to create something like an "AbstractEquatingCollection" class, which instead of using its elements' inherent equals
and hashCode
methods would instead have to use those of Equator
for all the basic methods, such as add
, contains
, etc. NB in fact when you look at the source code, AbstractCollection
does not implement add
, nor do its abstract subclasses such as AbstractSet
... you have to wait till the concrete classes such as HashSet
and ArrayList
before add
is implemented. Quite a headache.
In the mean time watch this space, I suppose. The obvious interim solution would be to wrap all your elements in a bespoke wrapper class which uses equals
and hashCode
to implement the kind of equality you want... then manipulate Collections
of these wrapper objects.
edited Jan 1 '17 at 20:36
answered Dec 9 '16 at 20:25
mike rodentmike rodent
4,09134261
4,09134261
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
add a comment |
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
Also, someone wise said "Know the cost of dependency"
– Stanislaw Baranski
Aug 6 '18 at 0:10
add a comment |
Converting the lists to Guava's Multiset works very well. They are compared regardless of their order and duplicate elements are taken into account as well.
static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}
assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));
add a comment |
Converting the lists to Guava's Multiset works very well. They are compared regardless of their order and duplicate elements are taken into account as well.
static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}
assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));
add a comment |
Converting the lists to Guava's Multiset works very well. They are compared regardless of their order and duplicate elements are taken into account as well.
static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}
assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));
Converting the lists to Guava's Multiset works very well. They are compared regardless of their order and duplicate elements are taken into account as well.
static <T> boolean equalsIgnoreOrder(List<T> a, List<T> b) {
return ImmutableMultiset.copyOf(a).equals(ImmutableMultiset.copyOf(b));
}
assert equalsIgnoreOrder(ImmutableList.of(3, 1, 2), ImmutableList.of(2, 1, 3));
assert !equalsIgnoreOrder(ImmutableList.of(1), ImmutableList.of(1, 1));
edited May 13 '16 at 16:34
answered May 13 '16 at 12:26
NatixNatix
9,84274365
9,84274365
add a comment |
add a comment |
Solution which leverages CollectionUtils subtract method:
import static org.apache.commons.collections15.CollectionUtils.subtract;
public class CollectionUtils {
static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
if (a == null && b == null)
return true;
if (a == null || b == null || a.size() != b.size())
return false;
return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
}
}
add a comment |
Solution which leverages CollectionUtils subtract method:
import static org.apache.commons.collections15.CollectionUtils.subtract;
public class CollectionUtils {
static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
if (a == null && b == null)
return true;
if (a == null || b == null || a.size() != b.size())
return false;
return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
}
}
add a comment |
Solution which leverages CollectionUtils subtract method:
import static org.apache.commons.collections15.CollectionUtils.subtract;
public class CollectionUtils {
static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
if (a == null && b == null)
return true;
if (a == null || b == null || a.size() != b.size())
return false;
return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
}
}
Solution which leverages CollectionUtils subtract method:
import static org.apache.commons.collections15.CollectionUtils.subtract;
public class CollectionUtils {
static public <T> boolean equals(Collection<? extends T> a, Collection<? extends T> b) {
if (a == null && b == null)
return true;
if (a == null || b == null || a.size() != b.size())
return false;
return subtract(a, b).size() == 0 && subtract(a, b).size() == 0;
}
}
answered Jan 28 '14 at 11:12
maxdanilkinmaxdanilkin
211
211
add a comment |
add a comment |
If you don't hope to sort the collections and you need the result that ["A" "B" "C"] is not equals to ["B" "B" "A" "C"],
l1.containsAll(l2)&&l2.containsAll(l1)
is not enough, you propably need to check the size too :
List<String> l1 =Arrays.asList("A","A","B","C");
List<String> l2 =Arrays.asList("A","B","C");
List<String> l3 =Arrays.asList("A","B","C");
System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected
System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected
public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}
add a comment |
If you don't hope to sort the collections and you need the result that ["A" "B" "C"] is not equals to ["B" "B" "A" "C"],
l1.containsAll(l2)&&l2.containsAll(l1)
is not enough, you propably need to check the size too :
List<String> l1 =Arrays.asList("A","A","B","C");
List<String> l2 =Arrays.asList("A","B","C");
List<String> l3 =Arrays.asList("A","B","C");
System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected
System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected
public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}
add a comment |
If you don't hope to sort the collections and you need the result that ["A" "B" "C"] is not equals to ["B" "B" "A" "C"],
l1.containsAll(l2)&&l2.containsAll(l1)
is not enough, you propably need to check the size too :
List<String> l1 =Arrays.asList("A","A","B","C");
List<String> l2 =Arrays.asList("A","B","C");
List<String> l3 =Arrays.asList("A","B","C");
System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected
System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected
public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}
If you don't hope to sort the collections and you need the result that ["A" "B" "C"] is not equals to ["B" "B" "A" "C"],
l1.containsAll(l2)&&l2.containsAll(l1)
is not enough, you propably need to check the size too :
List<String> l1 =Arrays.asList("A","A","B","C");
List<String> l2 =Arrays.asList("A","B","C");
List<String> l3 =Arrays.asList("A","B","C");
System.out.println(l1.containsAll(l2)&&l2.containsAll(l1));//cautions, this will be true
System.out.println(isListEqualsWithoutOrder(l1,l2));//false as expected
System.out.println(l3.containsAll(l2)&&l2.containsAll(l3));//true as expected
System.out.println(isListEqualsWithoutOrder(l2,l3));//true as expected
public static boolean isListEqualsWithoutOrder(List<String> l1, List<String> l2) {
return l1.size()==l2.size() && l1.containsAll(l2)&&l2.containsAll(l1);
}
answered Feb 20 '17 at 8:54
JaskeyJaskey
8,688875109
8,688875109
add a comment |
add a comment |
If you care about order, then just use the equals method:
list1.equals(list2)
If you don't care order then use this
Collections.sort(list1);
Collections.sort(list2);
list1.equals(list2)
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
add a comment |
If you care about order, then just use the equals method:
list1.equals(list2)
If you don't care order then use this
Collections.sort(list1);
Collections.sort(list2);
list1.equals(list2)
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
add a comment |
If you care about order, then just use the equals method:
list1.equals(list2)
If you don't care order then use this
Collections.sort(list1);
Collections.sort(list2);
list1.equals(list2)
If you care about order, then just use the equals method:
list1.equals(list2)
If you don't care order then use this
Collections.sort(list1);
Collections.sort(list2);
list1.equals(list2)
edited Nov 20 '18 at 6:31
answered Nov 24 '16 at 13:13
Ramesh KumarRamesh Kumar
9721324
9721324
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
add a comment |
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
2
2
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
He says he doesn't care about order.
– mike rodent
Dec 9 '16 at 20:28
add a comment |
Best of both worlds [@DiddiZ, @Chalkos]: this one mainly builds upon @Chalkos method, but fixes a bug (ifst.next()), and improves initial checks (taken from @DiddiZ) as well as removes the need to copy the first collection (just removes items from a copy of the second collection).
Not requiring a hashing function or sorting, and enabling an early exist on un-equality, this is the most efficient implementation yet. That is unless you have a collection length in the thousands or more, and a very simple hashing function.
public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
if (one == two)
return true;
// If either list is null, return whether the other is empty
if (one == null)
return two.isEmpty();
if (two == null)
return one.isEmpty();
// If lengths are not equal, they can't possibly match
if (one.size() != two.size())
return false;
// copy the second list, so it can be modified
final List<T> ctwo = new ArrayList<>(two);
for (T itm : one) {
Iterator<T> it = ctwo.iterator();
boolean gotEq = false;
while (it.hasNext()) {
if (itm.equals(it.next())) {
it.remove();
gotEq = true;
break;
}
}
if (!gotEq) return false;
}
// All elements in one were found in two, and they're the same size.
return true;
}
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
add a comment |
Best of both worlds [@DiddiZ, @Chalkos]: this one mainly builds upon @Chalkos method, but fixes a bug (ifst.next()), and improves initial checks (taken from @DiddiZ) as well as removes the need to copy the first collection (just removes items from a copy of the second collection).
Not requiring a hashing function or sorting, and enabling an early exist on un-equality, this is the most efficient implementation yet. That is unless you have a collection length in the thousands or more, and a very simple hashing function.
public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
if (one == two)
return true;
// If either list is null, return whether the other is empty
if (one == null)
return two.isEmpty();
if (two == null)
return one.isEmpty();
// If lengths are not equal, they can't possibly match
if (one.size() != two.size())
return false;
// copy the second list, so it can be modified
final List<T> ctwo = new ArrayList<>(two);
for (T itm : one) {
Iterator<T> it = ctwo.iterator();
boolean gotEq = false;
while (it.hasNext()) {
if (itm.equals(it.next())) {
it.remove();
gotEq = true;
break;
}
}
if (!gotEq) return false;
}
// All elements in one were found in two, and they're the same size.
return true;
}
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
add a comment |
Best of both worlds [@DiddiZ, @Chalkos]: this one mainly builds upon @Chalkos method, but fixes a bug (ifst.next()), and improves initial checks (taken from @DiddiZ) as well as removes the need to copy the first collection (just removes items from a copy of the second collection).
Not requiring a hashing function or sorting, and enabling an early exist on un-equality, this is the most efficient implementation yet. That is unless you have a collection length in the thousands or more, and a very simple hashing function.
public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
if (one == two)
return true;
// If either list is null, return whether the other is empty
if (one == null)
return two.isEmpty();
if (two == null)
return one.isEmpty();
// If lengths are not equal, they can't possibly match
if (one.size() != two.size())
return false;
// copy the second list, so it can be modified
final List<T> ctwo = new ArrayList<>(two);
for (T itm : one) {
Iterator<T> it = ctwo.iterator();
boolean gotEq = false;
while (it.hasNext()) {
if (itm.equals(it.next())) {
it.remove();
gotEq = true;
break;
}
}
if (!gotEq) return false;
}
// All elements in one were found in two, and they're the same size.
return true;
}
Best of both worlds [@DiddiZ, @Chalkos]: this one mainly builds upon @Chalkos method, but fixes a bug (ifst.next()), and improves initial checks (taken from @DiddiZ) as well as removes the need to copy the first collection (just removes items from a copy of the second collection).
Not requiring a hashing function or sorting, and enabling an early exist on un-equality, this is the most efficient implementation yet. That is unless you have a collection length in the thousands or more, and a very simple hashing function.
public static <T> boolean isCollectionMatch(Collection<T> one, Collection<T> two) {
if (one == two)
return true;
// If either list is null, return whether the other is empty
if (one == null)
return two.isEmpty();
if (two == null)
return one.isEmpty();
// If lengths are not equal, they can't possibly match
if (one.size() != two.size())
return false;
// copy the second list, so it can be modified
final List<T> ctwo = new ArrayList<>(two);
for (T itm : one) {
Iterator<T> it = ctwo.iterator();
boolean gotEq = false;
while (it.hasNext()) {
if (itm.equals(it.next())) {
it.remove();
gotEq = true;
break;
}
}
if (!gotEq) return false;
}
// All elements in one were found in two, and they're the same size.
return true;
}
edited Jan 8 '16 at 23:45
answered Jan 8 '16 at 12:00
jazzgiljazzgil
1,2591217
1,2591217
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
add a comment |
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
If I am not mistaken, the complexity of this algorithm in a worth case scenario (where the lists are equal but sorted in an opposite manner) would be O(N*N!).
– SatA
Jun 5 '16 at 11:39
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Actually, it would be O(N*(N/2)), as with each iteration, the array size decreases.
– jazzgil
Jun 6 '16 at 8:47
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
Oh my bad, you are correct, it would be O(N*(N/2))
– SatA
Jun 6 '16 at 9:30
add a comment |
It is an alternative way to check equality of array lists which can contain null values:
List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);
System.out.println(checkEquality(listA, listB)); // will return TRUE
private List<String> getSortedArrayList(List<String> arrayList)
{
String array = arrayList.toArray(new String[arrayList.size()]);
Arrays.sort(array, new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1 == null && o2 == null)
{
return 0;
}
if (o1 == null)
{
return 1;
}
if (o2 == null)
{
return -1;
}
return o1.compareTo(o2);
}
});
return new ArrayList(Arrays.asList(array));
}
private Boolean checkEquality(List<String> listA, List<String> listB)
{
listA = getSortedArrayList(listA);
listB = getSortedArrayList(listB);
String arrayA = listA.toArray(new String[listA.size()]);
String arrayB = listB.toArray(new String[listB.size()]);
return Arrays.deepEquals(arrayA, arrayB);
}
add a comment |
It is an alternative way to check equality of array lists which can contain null values:
List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);
System.out.println(checkEquality(listA, listB)); // will return TRUE
private List<String> getSortedArrayList(List<String> arrayList)
{
String array = arrayList.toArray(new String[arrayList.size()]);
Arrays.sort(array, new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1 == null && o2 == null)
{
return 0;
}
if (o1 == null)
{
return 1;
}
if (o2 == null)
{
return -1;
}
return o1.compareTo(o2);
}
});
return new ArrayList(Arrays.asList(array));
}
private Boolean checkEquality(List<String> listA, List<String> listB)
{
listA = getSortedArrayList(listA);
listB = getSortedArrayList(listB);
String arrayA = listA.toArray(new String[listA.size()]);
String arrayB = listB.toArray(new String[listB.size()]);
return Arrays.deepEquals(arrayA, arrayB);
}
add a comment |
It is an alternative way to check equality of array lists which can contain null values:
List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);
System.out.println(checkEquality(listA, listB)); // will return TRUE
private List<String> getSortedArrayList(List<String> arrayList)
{
String array = arrayList.toArray(new String[arrayList.size()]);
Arrays.sort(array, new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1 == null && o2 == null)
{
return 0;
}
if (o1 == null)
{
return 1;
}
if (o2 == null)
{
return -1;
}
return o1.compareTo(o2);
}
});
return new ArrayList(Arrays.asList(array));
}
private Boolean checkEquality(List<String> listA, List<String> listB)
{
listA = getSortedArrayList(listA);
listB = getSortedArrayList(listB);
String arrayA = listA.toArray(new String[listA.size()]);
String arrayB = listB.toArray(new String[listB.size()]);
return Arrays.deepEquals(arrayA, arrayB);
}
It is an alternative way to check equality of array lists which can contain null values:
List listA = Arrays.asList(null, "b", "c");
List listB = Arrays.asList("b", "c", null);
System.out.println(checkEquality(listA, listB)); // will return TRUE
private List<String> getSortedArrayList(List<String> arrayList)
{
String array = arrayList.toArray(new String[arrayList.size()]);
Arrays.sort(array, new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1 == null && o2 == null)
{
return 0;
}
if (o1 == null)
{
return 1;
}
if (o2 == null)
{
return -1;
}
return o1.compareTo(o2);
}
});
return new ArrayList(Arrays.asList(array));
}
private Boolean checkEquality(List<String> listA, List<String> listB)
{
listA = getSortedArrayList(listA);
listB = getSortedArrayList(listB);
String arrayA = listA.toArray(new String[listA.size()]);
String arrayB = listB.toArray(new String[listB.size()]);
return Arrays.deepEquals(arrayA, arrayB);
}
answered Aug 2 '16 at 14:28


Sa QadaSa Qada
4,07113541
4,07113541
add a comment |
add a comment |
My solution for this. It is not so cool, but works well.
public static boolean isEqualCollection(List<?> a, List<?> b) {
if (a == null || b == null) {
throw new NullPointerException("The list a and b must be not null.");
}
if (a.size() != b.size()) {
return false;
}
List<?> bCopy = new ArrayList<Object>(b);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < bCopy.size(); j++) {
if (a.get(i).equals(bCopy.get(j))) {
bCopy.remove(j);
break;
}
}
}
return bCopy.isEmpty();
}
add a comment |
My solution for this. It is not so cool, but works well.
public static boolean isEqualCollection(List<?> a, List<?> b) {
if (a == null || b == null) {
throw new NullPointerException("The list a and b must be not null.");
}
if (a.size() != b.size()) {
return false;
}
List<?> bCopy = new ArrayList<Object>(b);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < bCopy.size(); j++) {
if (a.get(i).equals(bCopy.get(j))) {
bCopy.remove(j);
break;
}
}
}
return bCopy.isEmpty();
}
add a comment |
My solution for this. It is not so cool, but works well.
public static boolean isEqualCollection(List<?> a, List<?> b) {
if (a == null || b == null) {
throw new NullPointerException("The list a and b must be not null.");
}
if (a.size() != b.size()) {
return false;
}
List<?> bCopy = new ArrayList<Object>(b);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < bCopy.size(); j++) {
if (a.get(i).equals(bCopy.get(j))) {
bCopy.remove(j);
break;
}
}
}
return bCopy.isEmpty();
}
My solution for this. It is not so cool, but works well.
public static boolean isEqualCollection(List<?> a, List<?> b) {
if (a == null || b == null) {
throw new NullPointerException("The list a and b must be not null.");
}
if (a.size() != b.size()) {
return false;
}
List<?> bCopy = new ArrayList<Object>(b);
for (int i = 0; i < a.size(); i++) {
for (int j = 0; j < bCopy.size(); j++) {
if (a.get(i).equals(bCopy.get(j))) {
bCopy.remove(j);
break;
}
}
}
return bCopy.isEmpty();
}
answered Jan 3 at 2:23
Cícero MouraCícero Moura
9001226
9001226
add a comment |
add a comment |
In that case lists {"a", "b"} and {"b","a"} are equal. And {"a", "b"} and {"b","a","c"} are not equal. If you use list of complex objects, remember to override equals method, as containsAll uses it inside.
if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
areEqual = true;
}
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code forAbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking aboutLists
, not aboutSets
. Please see my answer.
– mike rodent
Dec 12 '16 at 21:07
add a comment |
In that case lists {"a", "b"} and {"b","a"} are equal. And {"a", "b"} and {"b","a","c"} are not equal. If you use list of complex objects, remember to override equals method, as containsAll uses it inside.
if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
areEqual = true;
}
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code forAbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking aboutLists
, not aboutSets
. Please see my answer.
– mike rodent
Dec 12 '16 at 21:07
add a comment |
In that case lists {"a", "b"} and {"b","a"} are equal. And {"a", "b"} and {"b","a","c"} are not equal. If you use list of complex objects, remember to override equals method, as containsAll uses it inside.
if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
areEqual = true;
}
In that case lists {"a", "b"} and {"b","a"} are equal. And {"a", "b"} and {"b","a","c"} are not equal. If you use list of complex objects, remember to override equals method, as containsAll uses it inside.
if (oneList.size() == secondList.size() && oneList.containsAll(secondList)){
areEqual = true;
}
answered Dec 12 '16 at 14:39
AndrewAndrew
432317
432317
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code forAbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking aboutLists
, not aboutSets
. Please see my answer.
– mike rodent
Dec 12 '16 at 21:07
add a comment |
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code forAbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking aboutLists
, not aboutSets
. Please see my answer.
– mike rodent
Dec 12 '16 at 21:07
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code for
AbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking about Lists
, not about Sets
. Please see my answer.– mike rodent
Dec 12 '16 at 21:07
-1: gives the wrong answer with {"a", "a", "b"} and {"a", "b", "b"} : check out source code for
AbstractCollection.containsAll()
. You have to allow for having duplicate elements as we are talking about Lists
, not about Sets
. Please see my answer.– mike rodent
Dec 12 '16 at 21:07
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f13501142%2fjava-arraylist-how-can-i-tell-if-two-lists-are-equal-order-not-mattering%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
4
see the answer for this question: stackoverflow.com/a/1075699/1133011
– David Kroukamp
Nov 21 '12 at 20:04
See List.containsAll(list) in java
– Sahil Jain
Jan 1 '16 at 14:05