找到两个不同的列表是否包含完全相同的元素的简单方法?

时间:2022-10-17 14:01:16

What is the simplest way to find if two Lists contain exactly the same elements, in the standard Java libraries?

如果两个列表在标准Java库中包含完全相同的元素,最简单的方法是什么?

It shouldn't matter if the two Lists are the same instance or not, and it shouldn't matter if the type parameter of the Lists are different.

这两个列表是相同的实例还是不同的实例并不重要,列表的类型参数是否不同也不重要。

e.g.

如。

List list1
List<String> list2; 
// ... construct etc

list1.add("A");
list2.add("A"); 
// the function, given these two lists, should return true

There's probably something staring me in the face I know :-)

可能有什么东西盯着我,我知道:-)


EDIT: To clarify, I was looking for the EXACT same elements and number of elements, in order.

编辑:为了澄清这一点,我正在寻找完全相同的元素和元素的数量。


EDIT: Thanks for pointing out the obvious answer I couldn't see for looking :-)

编辑:谢谢你指出我找不到的明显答案:-)

Although all the answers given so far are correct, some are more correct than others, so I'll wait a while for the best rounded-off answer before accepting.

虽然到目前为止给出的答案都是正确的,但有些比其他的更正确,所以我将等待最好的完整答案后才能接受。

16 个解决方案

#1


252  

If you care about order, then just use the equals method:

如果你关心顺序,那么就用等号方法:

list1.equals(list2)

From the javadoc:

从javadoc:

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

将指定的对象与此列表进行比较,使其相等。如果且仅当指定对象也是一个列表时返回true,则两个列表的大小相同,两个列表中的所有对应元素对都相等。(两个元素e1和e2在(e1= null ?e2 = = null:. equals(e2)))。换句话说,如果两个列表以相同的顺序包含相同的元素,则定义为相等。此定义确保equals方法在列表接口的不同实现之间正常工作。

If you want to check independent of order, you could copy all of the elements to Sets and use equals on the resulting Sets:

如果您想要独立于顺序检查,您可以将所有元素复制到集合中,并在结果集上使用等号:

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

A limitation of this approach is that it not only ignores order, but also frequency of duplicate elements. For example, if list1 was ["A", "B", "A"] and list2 was ["A", "B", "B"] the Set approach would consider them to be equal.

这种方法的一个局限性是,它不仅忽略了顺序,而且还忽略了重复元素的频率。例如,如果清单1是[A", "B", "A"],而清单2是[A", "B", "B"],那么Set方法会认为它们是相等的。

If you need to be insensitive to order but sensitive to the frequency of duplicates you can either:

如果你需要对订单不敏感,但对重复频率敏感,你可以:

  • sort both lists (or copies) before comparing them, as done in this answer to another question
  • 在比较这两个列表(或副本)之前,先对它们进行排序,就像在回答另一个问题时所做的那样
  • or copy all elements to a Multiset
  • 或将所有元素复制到多集

#2


68  

I posted a bunch of stuff in comments I think it warrants its own answer.

我在评论中发表了一些东西,我认为它有理由给出自己的答案。

As everyone says here, using equals() depends on the order. If you don't care about order, you have 3 options.

正如这里的每个人所说,使用equals()取决于顺序。如果你不关心顺序,你有3种选择。

Option 1

选项1

Use containsAll(). This option is not ideal, in my opinion, because it offers worst case performance, O(n^2).

使用containsAll()。这个选项是不理想的,在我看来,因为它提供了最坏情况的性能,O(n ^ 2)。

Option 2

选项2

There are two variations to this:

对此有两种变体:

2a) If you don't care about maintaining the order ofyour lists... use Collections.sort() on both list. Then use the equals(). This is O(nlogn), because you do two sorts, and then an O(n) comparison.

如果你不关心你的列表的顺序……在两个列表中使用Collections.sort()。然后使用equals()。这是O(nlogn)因为你要做两种排序,然后是O(n)比较。

2b) If you need to maintain the lists' order, you can copy both lists first. THEN you can use solution 2a on both the copied lists. However this might be unattractive if copying is very expensive.

如果你需要保持列表的顺序,你可以先复制两个列表。然后你可以在两个复制的列表上使用解决方案2a。然而,如果复制非常昂贵,这可能没有吸引力。

This leads to:

这将导致:

Option 3

选项3

If your requirements are the same as part 2b, but copying is too expensive. You can use a TreeSet to do the sorting for you. Dump each list into its own TreeSet. It will be sorted in the set, and the original lists will remain intact. Then perform an equals() comparison on both TreeSets. The TreeSetss can be built in O(nlogn) time, and the equals() is O(n).

如果您的需求与第2b部分相同,但是复制太贵了。您可以使用TreeSet来为您进行排序。将每个列表转储到自己的树集中。它将在集合中进行排序,原始列表将保持不变。然后在两个TreeSets上执行一个equals()比较。树可以在O(nlogn)时间内构建,等号()是O(n)。

Take your pick :-).

随你挑吧:-)。

EDIT: I almost forgot the same caveat that Laurence Gonsalves points out. The TreeSet implementation will eliminate duplicates. If you care about duplicates, you will need some sort of sorted multiset.

编辑:我几乎忘记了劳伦斯·冈萨弗斯指出的同样的告诫。TreeSet实现将消除重复。如果您关心重复,您将需要某种排序的多集。

#3


5  

If you're using (or are happy to use) Apache Commons Collections, you can use CollectionUtils.isEqualCollection which "returns true iff the given Collections contain exactly the same elements with exactly the same cardinalities."

如果您正在使用(或乐于使用)Apache Commons集合,则可以使用CollectionUtils。isEqualCollection“返回真实的iff,给定集合包含的元素与基数完全相同”。

#4


5  

I know this is an old thread, but none of the other answers fully solved my use case (I guess Guava Multiset might do the same, but there is no example here). Please excuse my formatting. I am still new to posting on stack exchange. Additionally let me know if there are any errors

我知道这是一个旧的线程,但是其他的答案都不能完全解决我的用例(我猜Guava Multiset可能也会这样做,但是这里没有示例)。请原谅我的格式。我还是第一次在栈交换上发帖。另外,如果有任何错误,请告诉我

Lets say you have List<T> a and List<T> b and you want to check if they are equal with the following conditions:

假设你有List a和List b,你要检查它们是否等于以下条件:

1) O(n) expected running time
2) Equality is defined as: For all elements in a or b, the number of times the element occurs in a is equal to the number of times the element occurs in b. Element equality is defined as T.equals()

1) O(n)期望运行时间2)等式定义为:对于a或b中的所有元素,元素出现在a中的次数等于元素出现在b中的次数。

private boolean listsAreEquivelent(List<? extends Object> a, List<? extends Object> b) {
    if(a==null) {
        if(b==null) {
            //Here 2 null lists are equivelent. You may want to change this.
            return true;
        } else {
            return false;
        }
    }
    if(b==null) {
        return false;
    }
    Map<Object, Integer> tempMap = new HashMap<>();
    for(Object element : a) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            tempMap.put(element, 1);
        } else {
            tempMap.put(element, currentCount+1);
        }
    }
    for(Object element : b) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            return false;
        } else {
            tempMap.put(element, currentCount-1);
        }
    }
    for(Integer count : tempMap.values()) {
        if(count != 0) {
            return false;
        }
    }
    return true;
}

Running time is O(n) because we are doing O(2*n) insertions into a hashmap and O(3*n) hashmap selects. I have not fully tested this code, so beware :)

运行时间为O(n),因为我们正在对hashmap和O(3*n) hashmap选择进行O(2*n)插入。我还没有完全测试这段代码,所以请注意:)

//Returns true:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","A"));
listsAreEquivelent(null,null);
//Returns false:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),null);

#5


3  

Try this version which does not require order to be the same but does support having multiple of the same value. They match only if each has the same quantity of any value.

尝试这个版本,它不需要顺序相同,但是支持具有多个相同的值。它们只有在每个值的数量相同时才匹配。

public boolean arraysMatch(List<String> elements1, List<String> elements2) {
    // Optional quick test since size must match
    if (elements1.size() != elements2.size()) {
        return false;
    }
    List<String> work = newArrayList(elements2);
    for (String element : elements1) {
        if (!work.remove(element)) {
            return false;
        }
    }
    return work.isEmpty();
}

#6


2  

Solution for case when two lists have the same elements, but different order:

当两个列表的元素相同但顺序不同时的解决方案:

public boolean isDifferentLists(List<Integer> listOne, List<Integer> listTwo) {
    if(isNullLists(listOne, listTwo)) {
        return false;
    }

    if (hasDifferentSize(listOne, listTwo)) {
        return true;
    }

    List<Integer> listOneCopy = Lists.newArrayList(listOne);
    List<Integer> listTwoCopy = Lists.newArrayList(listTwo);
    listOneCopy.removeAll(listTwoCopy);

    return CollectionUtils.isNotEmpty(listOneCopy);
}

private boolean isNullLists(List<Integer> listOne, List<Integer> listTwo) {
    return listOne == null && listTwo == null;
}

private boolean hasDifferentSize(List<Integer> listOne, List<Integer> listTwo) {
    return (listOne == null && listTwo != null) || (listOne != null && listTwo == null) || (listOne.size() != listTwo.size());
}

#7


2  

Very late to the party but wanted to add this null safe check:

很晚才来,但想添加这个零安全检查:

Objects.equals(list1, list2)

#8


1  

The equals method on List will do this, Lists are ordered, so to be equal two Lists must have the same elements in the same order.

List上的equals方法可以做到这一点,List是有序的,所以要相等,两个List必须有相同的元素以相同的顺序排列。

return list1.equals(list2);

#9


1  

list1.equals(list2);

If your list contains a custom Class MyClass, this class must override the equals function.

如果您的列表包含一个自定义类MyClass,那么这个类必须重写equals函数。

 class MyClass
  {
  int field=0;
  @0verride
  public boolean equals(Object other)
        {
        if(this==other) return true;
        if(other==null || !(other instanceof MyClass)) return false;
        return this.field== MyClass.class.cast(other);
        }
  }

Note :if you want to test equals on a java.util.Set rather than a java.util.List, then your object must override the hashCode function.

注意:如果您想在java.util上测试equals。设置而不是java.util。列表,然后对象必须覆盖hashCode函数。

#10


1  

Sample code:

示例代码:

public static '<'T'>' boolean isListDifferent(List'<'T'>' previousList,
        List'<'T'>' newList) {

    int sizePrevoisList = -1;
    int sizeNewList = -1;

    if (previousList != null && !previousList.isEmpty()) {
        sizePrevoisList = previousList.size();
    }
    if (newList != null && !newList.isEmpty()) {
        sizeNewList = newList.size();
    }

    if ((sizePrevoisList == -1) && (sizeNewList == -1)) {
        return false;
    }

    if (sizeNewList != sizePrevoisList) {
        return true;
    }

    List n_prevois = new ArrayList(previousList);
    List n_new = new ArrayList(newList);

    try {
        Collections.sort(n_prevois);
        Collections.sort(n_new);
    } catch (ClassCastException exp) {
        return true;
    }

    for (int i = 0; i < sizeNewList; i++) {
        Object obj_prevois = n_prevois.get(i);
        Object obj_new = n_new.get(i);
        if (obj_new.equals(obj_prevois)) {
            // Object are same
        } else {
            return true;
        }
    }

    return false;
}

#11


1  

Tom's answer is excellent I agree fully with his answers!

汤姆的回答很好,我完全同意他的回答!

An interesting aspect of this question is, whether you need the List type itself and its inherent ordering.

这个问题的一个有趣的方面是,您是否需要List类型本身及其固有的排序。

If not you can degrade to Iterable or Collection which gives you some flexibility on passing around data structures that are sorted on insertion time, rather than at the time when you want to check.

如果没有,您可以降级为可迭代的或可收集的,这使您在传递按插入时间排序的数据结构时具有一定的灵活性,而不是在需要检查的时候。

If the order never matters (and you don't have duplicate elements) consider using a Set.

如果顺序从来都不重要(而且没有重复的元素),考虑使用集合。

If the order matters but is defined by insertion time (and you don't have duplicates) consider a LinkedHashSet which is like a TreeSet but is ordered by insertion time (duplicates are not counted). This also gives you O(1) amortized access insted of O(log n).

如果顺序很重要,但由插入时间(并且没有重复)定义,请考虑一个LinkedHashSet,它类似于TreeSet,但按插入时间排序(不计算重复)。这也给了你O(1) O(log n)的平摊访问。

#12


0  

List.equals()

List.equals()

http://java.sun.com/j2se/1.5/docs/api/java/util/List.html#equals(java.lang.Object)

http://java.sun.com/j2se/1.5/docs/api/java/util/List.html =(java . lang . object)

#13


0  

You can use Apache's org.apache.commons.collections library: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html

您可以使用Apache的org.apache.commons.collections库:http://commons.apache.org/collections/apidocdocs/org/apache/commons/collections/listutils.html

public static boolean isEqualList(java.util.Collection list1,
                              java.util.Collection list2)

#14


0  

Check both lists are not nulls. If their sizes are different, then these lists are not equal. Build maps consisting of the lists' elements as keys and their repeats as values and compare the maps.

检查两个列表都不是null。如果它们的大小不同,那么这些列表就不相等。构建映射,将列表的元素作为键,将重复的元素作为值,并对映射进行比较。

Assumptions, if both lists are nulls, I consider them equal.

假设,如果两个列表都是空的,我认为它们是相等的。

private boolean compareLists(List<?> l1, List<?> l2) {
    if (l1 == null && l2 == null) {
        return true;
    } else if (l1 == null || l2 == null) {
        return false;
    }

    if (l1.size() != l2.size()) {
        return false;
    }

    Map<?, Integer> m1 = toMap(l1);
    Map<?, Integer> m2 = toMap(l2);

    return m1.equals(m2);
}

private Map<Object, Integer> toMap(List<?> list) {
    //Effective size, not to resize in the future.
    int mapSize = (int) (list.size() / 0.75 + 1);
    Map<Object, Integer> map = new HashMap<>(mapSize);

    for (Object o : list) {
        Integer count = map.get(o);
        if (count == null) {
            map.put(o, 1);
        } else {
            map.put(o, ++count);
        }
    }

    System.out.println(map);
    return map;
}

Please, note, method equals should be properly defined for these objects. https://*.com/a/24814634/4587961

请注意,对于这些对象,方法等号应该正确定义。https://*.com/a/24814634/4587961

#15


0  

In addition to Laurence's answer, if you also want to make it null-safe:

除了劳伦斯的回答,如果你也想使它无效-安全:

private static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    if (list1 == null)
        return list2==null;
    if (list2 == null)
        return list1 == null;
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

#16


-2  

It depends on what concrete List class you are using. The abstract class AbstractCollection has a method called containsAll(Collection) that takes another collection ( a List is a collection) and:

这取决于您使用的具体列表类。抽象类AbstractCollection有一个名为containsAll(Collection)的方法,它接受另一个Collection (List是Collection),并且:

Returns true if this collection contains all of the elements in the specified collection.

如果此集合包含指定集合中的所有元素,则返回true。

So if an ArrayList is being passed in you can call this method to see if they are exactly the same.

如果一个ArrayList被传入,你可以调用这个方法看看它们是否完全相同。

       List foo = new ArrayList();
    List bar = new ArrayList();
    String str = "foobar";

    foo.add(str);
    bar.add(str);

    foo.containsAll(bar);

The reason for containsAll() is because it iterates through the first list looking for the match in the second list. So if they are out of order equals() will not pick it up.

containsAll()的原因是它遍历第一个列表,寻找第二个列表中的匹配项。所以如果它们是无序的=()就不会把它捡起来。

EDIT: I just want to make a comment here about the amortized running time of performing the various options being offered. Is running time important? Sure. Is it the only thing you should consider? No.

编辑:我只是想在这里对执行所提供的各种选项的平摊运行时间做一个评论。运行时间重要吗?确定。这是你唯一应该考虑的事情吗?不。

The cost of copying EVERY single element from your lists into other lists takes time, and it also takes up a good chunk of memory (effectively doubling the memory you are using).

将列表中的每个元素复制到其他列表中需要花费大量的时间,而且还占用了大量内存(有效地将内存增加了一倍)。

So if memory in your JVM isn't a concern (which it should generally be) then you still need to consider the time it takes to copy every element from two lists into two TreeSets. Remember it is sorting every element as it enters them.

因此,如果您的JVM中的内存不是问题(通常应该是),那么您仍然需要考虑将两个列表中的每个元素复制到两个TreeSets所需的时间。记住,它在输入元素时对每个元素进行排序。

My final advice? You need to consider your data set and how many elements you have in your data set, and also how large each object in your data set is before you can make a good decision here. Play around with them, create one each way and see which one runs faster. It's a good exercise.

我最后的建议吗?您需要考虑数据集和数据集中有多少元素,以及数据集中的每个对象有多大,然后才能在这里做出正确的决定。和他们一起玩,创造一种每一种方式,看哪一个跑得更快。这是一个很好的锻炼。

#1


252  

If you care about order, then just use the equals method:

如果你关心顺序,那么就用等号方法:

list1.equals(list2)

From the javadoc:

从javadoc:

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

将指定的对象与此列表进行比较,使其相等。如果且仅当指定对象也是一个列表时返回true,则两个列表的大小相同,两个列表中的所有对应元素对都相等。(两个元素e1和e2在(e1= null ?e2 = = null:. equals(e2)))。换句话说,如果两个列表以相同的顺序包含相同的元素,则定义为相等。此定义确保equals方法在列表接口的不同实现之间正常工作。

If you want to check independent of order, you could copy all of the elements to Sets and use equals on the resulting Sets:

如果您想要独立于顺序检查,您可以将所有元素复制到集合中,并在结果集上使用等号:

public static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

A limitation of this approach is that it not only ignores order, but also frequency of duplicate elements. For example, if list1 was ["A", "B", "A"] and list2 was ["A", "B", "B"] the Set approach would consider them to be equal.

这种方法的一个局限性是,它不仅忽略了顺序,而且还忽略了重复元素的频率。例如,如果清单1是[A", "B", "A"],而清单2是[A", "B", "B"],那么Set方法会认为它们是相等的。

If you need to be insensitive to order but sensitive to the frequency of duplicates you can either:

如果你需要对订单不敏感,但对重复频率敏感,你可以:

  • sort both lists (or copies) before comparing them, as done in this answer to another question
  • 在比较这两个列表(或副本)之前,先对它们进行排序,就像在回答另一个问题时所做的那样
  • or copy all elements to a Multiset
  • 或将所有元素复制到多集

#2


68  

I posted a bunch of stuff in comments I think it warrants its own answer.

我在评论中发表了一些东西,我认为它有理由给出自己的答案。

As everyone says here, using equals() depends on the order. If you don't care about order, you have 3 options.

正如这里的每个人所说,使用equals()取决于顺序。如果你不关心顺序,你有3种选择。

Option 1

选项1

Use containsAll(). This option is not ideal, in my opinion, because it offers worst case performance, O(n^2).

使用containsAll()。这个选项是不理想的,在我看来,因为它提供了最坏情况的性能,O(n ^ 2)。

Option 2

选项2

There are two variations to this:

对此有两种变体:

2a) If you don't care about maintaining the order ofyour lists... use Collections.sort() on both list. Then use the equals(). This is O(nlogn), because you do two sorts, and then an O(n) comparison.

如果你不关心你的列表的顺序……在两个列表中使用Collections.sort()。然后使用equals()。这是O(nlogn)因为你要做两种排序,然后是O(n)比较。

2b) If you need to maintain the lists' order, you can copy both lists first. THEN you can use solution 2a on both the copied lists. However this might be unattractive if copying is very expensive.

如果你需要保持列表的顺序,你可以先复制两个列表。然后你可以在两个复制的列表上使用解决方案2a。然而,如果复制非常昂贵,这可能没有吸引力。

This leads to:

这将导致:

Option 3

选项3

If your requirements are the same as part 2b, but copying is too expensive. You can use a TreeSet to do the sorting for you. Dump each list into its own TreeSet. It will be sorted in the set, and the original lists will remain intact. Then perform an equals() comparison on both TreeSets. The TreeSetss can be built in O(nlogn) time, and the equals() is O(n).

如果您的需求与第2b部分相同,但是复制太贵了。您可以使用TreeSet来为您进行排序。将每个列表转储到自己的树集中。它将在集合中进行排序,原始列表将保持不变。然后在两个TreeSets上执行一个equals()比较。树可以在O(nlogn)时间内构建,等号()是O(n)。

Take your pick :-).

随你挑吧:-)。

EDIT: I almost forgot the same caveat that Laurence Gonsalves points out. The TreeSet implementation will eliminate duplicates. If you care about duplicates, you will need some sort of sorted multiset.

编辑:我几乎忘记了劳伦斯·冈萨弗斯指出的同样的告诫。TreeSet实现将消除重复。如果您关心重复,您将需要某种排序的多集。

#3


5  

If you're using (or are happy to use) Apache Commons Collections, you can use CollectionUtils.isEqualCollection which "returns true iff the given Collections contain exactly the same elements with exactly the same cardinalities."

如果您正在使用(或乐于使用)Apache Commons集合,则可以使用CollectionUtils。isEqualCollection“返回真实的iff,给定集合包含的元素与基数完全相同”。

#4


5  

I know this is an old thread, but none of the other answers fully solved my use case (I guess Guava Multiset might do the same, but there is no example here). Please excuse my formatting. I am still new to posting on stack exchange. Additionally let me know if there are any errors

我知道这是一个旧的线程,但是其他的答案都不能完全解决我的用例(我猜Guava Multiset可能也会这样做,但是这里没有示例)。请原谅我的格式。我还是第一次在栈交换上发帖。另外,如果有任何错误,请告诉我

Lets say you have List<T> a and List<T> b and you want to check if they are equal with the following conditions:

假设你有List a和List b,你要检查它们是否等于以下条件:

1) O(n) expected running time
2) Equality is defined as: For all elements in a or b, the number of times the element occurs in a is equal to the number of times the element occurs in b. Element equality is defined as T.equals()

1) O(n)期望运行时间2)等式定义为:对于a或b中的所有元素,元素出现在a中的次数等于元素出现在b中的次数。

private boolean listsAreEquivelent(List<? extends Object> a, List<? extends Object> b) {
    if(a==null) {
        if(b==null) {
            //Here 2 null lists are equivelent. You may want to change this.
            return true;
        } else {
            return false;
        }
    }
    if(b==null) {
        return false;
    }
    Map<Object, Integer> tempMap = new HashMap<>();
    for(Object element : a) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            tempMap.put(element, 1);
        } else {
            tempMap.put(element, currentCount+1);
        }
    }
    for(Object element : b) {
        Integer currentCount = tempMap.get(element);
        if(currentCount == null) {
            return false;
        } else {
            tempMap.put(element, currentCount-1);
        }
    }
    for(Integer count : tempMap.values()) {
        if(count != 0) {
            return false;
        }
    }
    return true;
}

Running time is O(n) because we are doing O(2*n) insertions into a hashmap and O(3*n) hashmap selects. I have not fully tested this code, so beware :)

运行时间为O(n),因为我们正在对hashmap和O(3*n) hashmap选择进行O(2*n)插入。我还没有完全测试这段代码,所以请注意:)

//Returns true:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","A"));
listsAreEquivelent(null,null);
//Returns false:
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("B","A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),Arrays.asList("A","B"));
listsAreEquivelent(Arrays.asList("A","A","B"),null);

#5


3  

Try this version which does not require order to be the same but does support having multiple of the same value. They match only if each has the same quantity of any value.

尝试这个版本,它不需要顺序相同,但是支持具有多个相同的值。它们只有在每个值的数量相同时才匹配。

public boolean arraysMatch(List<String> elements1, List<String> elements2) {
    // Optional quick test since size must match
    if (elements1.size() != elements2.size()) {
        return false;
    }
    List<String> work = newArrayList(elements2);
    for (String element : elements1) {
        if (!work.remove(element)) {
            return false;
        }
    }
    return work.isEmpty();
}

#6


2  

Solution for case when two lists have the same elements, but different order:

当两个列表的元素相同但顺序不同时的解决方案:

public boolean isDifferentLists(List<Integer> listOne, List<Integer> listTwo) {
    if(isNullLists(listOne, listTwo)) {
        return false;
    }

    if (hasDifferentSize(listOne, listTwo)) {
        return true;
    }

    List<Integer> listOneCopy = Lists.newArrayList(listOne);
    List<Integer> listTwoCopy = Lists.newArrayList(listTwo);
    listOneCopy.removeAll(listTwoCopy);

    return CollectionUtils.isNotEmpty(listOneCopy);
}

private boolean isNullLists(List<Integer> listOne, List<Integer> listTwo) {
    return listOne == null && listTwo == null;
}

private boolean hasDifferentSize(List<Integer> listOne, List<Integer> listTwo) {
    return (listOne == null && listTwo != null) || (listOne != null && listTwo == null) || (listOne.size() != listTwo.size());
}

#7


2  

Very late to the party but wanted to add this null safe check:

很晚才来,但想添加这个零安全检查:

Objects.equals(list1, list2)

#8


1  

The equals method on List will do this, Lists are ordered, so to be equal two Lists must have the same elements in the same order.

List上的equals方法可以做到这一点,List是有序的,所以要相等,两个List必须有相同的元素以相同的顺序排列。

return list1.equals(list2);

#9


1  

list1.equals(list2);

If your list contains a custom Class MyClass, this class must override the equals function.

如果您的列表包含一个自定义类MyClass,那么这个类必须重写equals函数。

 class MyClass
  {
  int field=0;
  @0verride
  public boolean equals(Object other)
        {
        if(this==other) return true;
        if(other==null || !(other instanceof MyClass)) return false;
        return this.field== MyClass.class.cast(other);
        }
  }

Note :if you want to test equals on a java.util.Set rather than a java.util.List, then your object must override the hashCode function.

注意:如果您想在java.util上测试equals。设置而不是java.util。列表,然后对象必须覆盖hashCode函数。

#10


1  

Sample code:

示例代码:

public static '<'T'>' boolean isListDifferent(List'<'T'>' previousList,
        List'<'T'>' newList) {

    int sizePrevoisList = -1;
    int sizeNewList = -1;

    if (previousList != null && !previousList.isEmpty()) {
        sizePrevoisList = previousList.size();
    }
    if (newList != null && !newList.isEmpty()) {
        sizeNewList = newList.size();
    }

    if ((sizePrevoisList == -1) && (sizeNewList == -1)) {
        return false;
    }

    if (sizeNewList != sizePrevoisList) {
        return true;
    }

    List n_prevois = new ArrayList(previousList);
    List n_new = new ArrayList(newList);

    try {
        Collections.sort(n_prevois);
        Collections.sort(n_new);
    } catch (ClassCastException exp) {
        return true;
    }

    for (int i = 0; i < sizeNewList; i++) {
        Object obj_prevois = n_prevois.get(i);
        Object obj_new = n_new.get(i);
        if (obj_new.equals(obj_prevois)) {
            // Object are same
        } else {
            return true;
        }
    }

    return false;
}

#11


1  

Tom's answer is excellent I agree fully with his answers!

汤姆的回答很好,我完全同意他的回答!

An interesting aspect of this question is, whether you need the List type itself and its inherent ordering.

这个问题的一个有趣的方面是,您是否需要List类型本身及其固有的排序。

If not you can degrade to Iterable or Collection which gives you some flexibility on passing around data structures that are sorted on insertion time, rather than at the time when you want to check.

如果没有,您可以降级为可迭代的或可收集的,这使您在传递按插入时间排序的数据结构时具有一定的灵活性,而不是在需要检查的时候。

If the order never matters (and you don't have duplicate elements) consider using a Set.

如果顺序从来都不重要(而且没有重复的元素),考虑使用集合。

If the order matters but is defined by insertion time (and you don't have duplicates) consider a LinkedHashSet which is like a TreeSet but is ordered by insertion time (duplicates are not counted). This also gives you O(1) amortized access insted of O(log n).

如果顺序很重要,但由插入时间(并且没有重复)定义,请考虑一个LinkedHashSet,它类似于TreeSet,但按插入时间排序(不计算重复)。这也给了你O(1) O(log n)的平摊访问。

#12


0  

List.equals()

List.equals()

http://java.sun.com/j2se/1.5/docs/api/java/util/List.html#equals(java.lang.Object)

http://java.sun.com/j2se/1.5/docs/api/java/util/List.html =(java . lang . object)

#13


0  

You can use Apache's org.apache.commons.collections library: http://commons.apache.org/collections/apidocs/org/apache/commons/collections/ListUtils.html

您可以使用Apache的org.apache.commons.collections库:http://commons.apache.org/collections/apidocdocs/org/apache/commons/collections/listutils.html

public static boolean isEqualList(java.util.Collection list1,
                              java.util.Collection list2)

#14


0  

Check both lists are not nulls. If their sizes are different, then these lists are not equal. Build maps consisting of the lists' elements as keys and their repeats as values and compare the maps.

检查两个列表都不是null。如果它们的大小不同,那么这些列表就不相等。构建映射,将列表的元素作为键,将重复的元素作为值,并对映射进行比较。

Assumptions, if both lists are nulls, I consider them equal.

假设,如果两个列表都是空的,我认为它们是相等的。

private boolean compareLists(List<?> l1, List<?> l2) {
    if (l1 == null && l2 == null) {
        return true;
    } else if (l1 == null || l2 == null) {
        return false;
    }

    if (l1.size() != l2.size()) {
        return false;
    }

    Map<?, Integer> m1 = toMap(l1);
    Map<?, Integer> m2 = toMap(l2);

    return m1.equals(m2);
}

private Map<Object, Integer> toMap(List<?> list) {
    //Effective size, not to resize in the future.
    int mapSize = (int) (list.size() / 0.75 + 1);
    Map<Object, Integer> map = new HashMap<>(mapSize);

    for (Object o : list) {
        Integer count = map.get(o);
        if (count == null) {
            map.put(o, 1);
        } else {
            map.put(o, ++count);
        }
    }

    System.out.println(map);
    return map;
}

Please, note, method equals should be properly defined for these objects. https://*.com/a/24814634/4587961

请注意,对于这些对象,方法等号应该正确定义。https://*.com/a/24814634/4587961

#15


0  

In addition to Laurence's answer, if you also want to make it null-safe:

除了劳伦斯的回答,如果你也想使它无效-安全:

private static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    if (list1 == null)
        return list2==null;
    if (list2 == null)
        return list1 == null;
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}

#16


-2  

It depends on what concrete List class you are using. The abstract class AbstractCollection has a method called containsAll(Collection) that takes another collection ( a List is a collection) and:

这取决于您使用的具体列表类。抽象类AbstractCollection有一个名为containsAll(Collection)的方法,它接受另一个Collection (List是Collection),并且:

Returns true if this collection contains all of the elements in the specified collection.

如果此集合包含指定集合中的所有元素,则返回true。

So if an ArrayList is being passed in you can call this method to see if they are exactly the same.

如果一个ArrayList被传入,你可以调用这个方法看看它们是否完全相同。

       List foo = new ArrayList();
    List bar = new ArrayList();
    String str = "foobar";

    foo.add(str);
    bar.add(str);

    foo.containsAll(bar);

The reason for containsAll() is because it iterates through the first list looking for the match in the second list. So if they are out of order equals() will not pick it up.

containsAll()的原因是它遍历第一个列表,寻找第二个列表中的匹配项。所以如果它们是无序的=()就不会把它捡起来。

EDIT: I just want to make a comment here about the amortized running time of performing the various options being offered. Is running time important? Sure. Is it the only thing you should consider? No.

编辑:我只是想在这里对执行所提供的各种选项的平摊运行时间做一个评论。运行时间重要吗?确定。这是你唯一应该考虑的事情吗?不。

The cost of copying EVERY single element from your lists into other lists takes time, and it also takes up a good chunk of memory (effectively doubling the memory you are using).

将列表中的每个元素复制到其他列表中需要花费大量的时间,而且还占用了大量内存(有效地将内存增加了一倍)。

So if memory in your JVM isn't a concern (which it should generally be) then you still need to consider the time it takes to copy every element from two lists into two TreeSets. Remember it is sorting every element as it enters them.

因此,如果您的JVM中的内存不是问题(通常应该是),那么您仍然需要考虑将两个列表中的每个元素复制到两个TreeSets所需的时间。记住,它在输入元素时对每个元素进行排序。

My final advice? You need to consider your data set and how many elements you have in your data set, and also how large each object in your data set is before you can make a good decision here. Play around with them, create one each way and see which one runs faster. It's a good exercise.

我最后的建议吗?您需要考虑数据集和数据集中有多少元素,以及数据集中的每个对象有多大,然后才能在这里做出正确的决定。和他们一起玩,创造一种每一种方式,看哪一个跑得更快。这是一个很好的锻炼。