Java比较无序的ArrayLists

时间:2013-11-18 18:10:33

标签: java arraylist unordered

任何人都知道一种有效的方法来决定两个arraylists是否包含相同的值?

代码:

ArrayList<String> dummy1= new ArrayList<String>();
list1.put("foo");
list1.put("baa");

ArrayList<String> dummy2= new ArrayList<String>();
list1.put("baa");
list1.put("foo");

dummy1 == dummy2

挑战在于,arraylists的价值秩序不同......

(foo, baa) == (foo, baa) // per definition :)

我需要得到这个

(foo, baa) == (baa, foo) // true

那你的方法是什么?

8 个答案:

答案 0 :(得分:7)

首先排序。

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);
}

老实说,您应该检查您的数据结构决策。这似乎更像是一个问题。排序然后比较将采用O(nlog n),而HashSet比较将仅为O(n)。

答案 1 :(得分:6)

sort方法在O(n log n)中运行,但我们可以做得更好。首先执行空值和大小比较。然后使用HashMap<String, Integer>并将特定字符串的频率存储为值。对其中一个列表执行此操作,然后迭代另一个列表并检查映射是否包含字符串并具有相同的频率。这种方法是O(n)。

答案 2 :(得分:3)

假设列表中没有重复项,您可以使用两个临时HashSet<String>对象。

从您正在比较的两个String构建ArrayList<String>的集合,然后检查第一个集合是否包含第二个列表中的所有项目,第二个集合包含来自第二个列表的所有项目第一个清单。

你可以这样做:

List<String> a = ...;
List<String> b = ...;
Set<String> setA = new HashSet<String>(a);
Set<String> setB = new HashSet<String>(b);
boolean same = setA.containsAll(b) && setB.containsAll(a);

如果您必须考虑重复项,请将HashSet<String>替换为HashMap<String,Integer>,以制作并比较相应的频率计数器。

答案 3 :(得分:2)

您应该对两个ArrayLists进行排序,然后进行相同的比较。但是,您可能需要删除重复项(我不确定您的重复项政策)。

答案 4 :(得分:2)

最有效的方法取决于数组的大小。

  • 对于非常小的列表,使用contains()可能效率最高。 (也许对于0到5个元素的列表......我猜。)

  • 对于中型到大型的列表,您可以:

    • 对两个数组列表进行排序并逐对比对,

    • 对一个列表进行排序,并使用二进制搜索来探测第二个列表中的值。

    • 将一个转换为HashSet并使用第二个中的值进行探测。

复杂性分析并不简单,因为它取决于列表是否相等的可能性。 “最坏情况”是列表相同时,因为这意味着您必须先检查所有元素,然后才能返回true。在这种情况下,复杂性分别为O(N^2)O(NlogN)O(NlogN)O(N)

这没有考虑到空间使用,以及(在Java中)使用大量内存对性能的影响,

还存在“比例常数”的问题;例如对于O(NlogN)的小值,O(N)可能比N快。

简而言之......没有单一的解决方案总是最好的。

答案 5 :(得分:1)

答案 6 :(得分:1)

这里有Java 8,请指明您是否需要Java 7解决方案。

假设1:ArrayList不是空的。

其时间复杂度为O(N),其中N是任何输入的大小。

除输入外,其内存复杂度为0(N)

换句话说,它的时间和内存复杂度是线性的。

理论上,您可能会有O(1)内存复杂度不变,但它会将a1中的元素添加到setA1中。在我看来,这对垃圾收集器太过依赖,所以希望这个解决方案对你来说已经足够了。

import java.util.*;

public class ArraySameValuesSolver {

    public boolean of(List<String> list1, List<String> list2) {
        if (list1.size() != list2.size())
            return false;
        Map<String, Integer> occ = new HashMap<>();
        list1.stream().forEach(s -> incrementOccurences(occ, s));
        for (String s: list2) {
            decrementOccurrences(occ, s);
            if (occ.get(s) < 0)
                return false;
        }
        return true;
    }

    private void incrementOccurences(Map<String, Integer> occ, String s) {
        if (!occ.containsKey(s))
            occ.put(s, 1);
        else
            occ.put(s, occ.get(s) + 1);
    }

    private void decrementOccurrences(Map<String, Integer> occ, String s) {
        if (!occ.containsKey(s))
            occ.put(s, -1);
        else
            occ.put(s, occ.get(s) - 1);
    }

}

答案 7 :(得分:0)

  public boolean isListEquals( List listA , List listB ) {
    boolean result = false;

    if ( ( listA == listB ) ) {
      result = true;
      return result;
    }

    if ( ( listA == null ) || ( listB == null ) ) {
      return result;
    }

    if ( listA.size() != listB.size() ) {
      return result;
    }

    List listC = new ArrayList( listA );
    listC.removeAll( listB );
    if ( listC.size() > 0 ) {
      return result;
    }

    result = true;
    return result;
  }