任何人都知道一种有效的方法来决定两个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
那你的方法是什么?
答案 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)
你可以在这里找到你的答案,
http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained
使用比较链,
希望这对你有用。
此致 Ashok Gudise。
答案 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;
}