Java 如何计算两个 ArrayList 之间的差异?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/919387/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I calculate the difference between two ArrayLists?
提问by naveen
I have two ArrayLists.
我有两个 ArrayList。
ArrayList A contains:
ArrayList A 包含:
['2009-05-18','2009-05-19','2009-05-21']
ArrayList B contains:
ArrayList B 包含:
['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']
I have to compare ArrayList A and ArrayList B. The result ArrayList should contain the List which does not exist in ArrayList A.
我必须比较 ArrayList A 和 ArrayList B。结果 ArrayList 应该包含在 ArrayList A 中不存在的 List。
ArrayList result should be:
ArrayList 结果应该是:
['2009-05-20','2009-05-22']
how to compare ?
如何比较?
采纳答案by William Brendel
In Java, you can use the Collection
interface's removeAll
method.
在 Java 中,您可以使用Collection
接口的removeAll
方法。
// Create a couple ArrayList objects and populate them
// with some delicious fruits.
Collection firstList = new ArrayList() {{
add("apple");
add("orange");
}};
Collection secondList = new ArrayList() {{
add("apple");
add("orange");
add("banana");
add("strawberry");
}};
// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Remove all elements in firstList from secondList
secondList.removeAll(firstList);
// Show the "after" list
System.out.println("Result: " + secondList);
The above code will produce the following output:
上面的代码将产生以下输出:
First List: [apple, orange]
Second List: [apple, orange, banana, strawberry]
Result: [banana, strawberry]
回答by Josh
EDIT: Original question did not specify language. My answer is in C#.
编辑:原始问题没有指定语言。我的答案是在 C# 中。
You should instead use HashSet for this purpose. If you must use ArrayList, you could use the following extension methods:
为此,您应该改用 HashSet。如果必须使用 ArrayList,则可以使用以下扩展方法:
var a = arrayListA.Cast<DateTime>();
var b = arrayListB.Cast<DateTime>();
var c = b.Except(a);
var arrayListC = new ArrayList(c.ToArray());
using HashSet...
使用哈希集...
var a = new HashSet<DateTime>(); // ...and fill it
var b = new HashSet<DateTime>(); // ...and fill it
b.ExceptWith(a); // removes from b items that are in a
回答by Pavels
I guess you're talking about C#. If so, you can try this
我猜你在谈论 C#。如果是这样,你可以试试这个
ArrayList CompareArrayList(ArrayList a, ArrayList b)
{
ArrayList output = new ArrayList();
for (int i = 0; i < a.Count; i++)
{
string str = (string)a[i];
if (!b.Contains(str))
{
if(!output.Contains(str)) // check for dupes
output.Add(str);
}
}
return output;
}
回答by Demi
You are just comparing strings.
您只是在比较字符串。
Put the values in ArrayList A as keys in HashTable A.
Put the values in ArrayList B as keys in HashTable B.
将 ArrayList A 中的值作为 HashTable A 中的键。
将 ArrayList B 中的值作为 HashTable B 中的键。
Then, for each key in HashTable A, remove it from HashTable B if it exists.
然后,对于 HashTable A 中的每个键,如果存在,则将其从 HashTable B 中删除。
What you are left with in HashTable B are the strings (keys) that were not values in ArrayList A.
您在 HashTable B 中剩下的是不是 ArrayList A 中的值的字符串(键)。
C# (3.0) example added in response to request for code:
为响应代码请求而添加的 C# (3.0) 示例:
List<string> listA = new List<string>{"2009-05-18","2009-05-19","2009-05-21'"};
List<string> listB = new List<string>{"2009-05-18","2009-05-18","2009-05-19","2009-05-19","2009-05-20","2009-05-21","2009-05-21","2009-05-22"};
HashSet<string> hashA = new HashSet<string>();
HashSet<string> hashB = new HashSet<string>();
foreach (string dateStrA in listA) hashA.Add(dateStrA);
foreach (string dateStrB in listB) hashB.Add(dateStrB);
foreach (string dateStrA in hashA)
{
if (hashB.Contains(dateStrA)) hashB.Remove(dateStrA);
}
List<string> result = hashB.ToList<string>();
回答by andrii
You already have the right answer. And if you want to make more complicated and interesting operations between Lists (collections) use apache commons collections(CollectionUtils) It allows you to make conjuction/disjunction, find intersection, check if one collection is a subset of another and other nice things.
你已经有了正确的答案。如果您想在列表(集合)之间进行更复杂和有趣的操作,请使用apache 公共集合(CollectionUtils)它允许您进行连接/分离、查找交集、检查一个集合是否是另一个集合的子集以及其他好东西。
回答by Raj Mohamad
Hi use this class this will compare both lists and shows exactly the mismatch b/w both lists.
嗨,使用这个类,这将比较两个列表并准确显示两个列表的黑白不匹配。
import java.util.ArrayList;
import java.util.List;
public class ListCompare {
/**
* @param args
*/
public static void main(String[] args) {
List<String> dbVinList;
dbVinList = new ArrayList<String>();
List<String> ediVinList;
ediVinList = new ArrayList<String>();
dbVinList.add("A");
dbVinList.add("B");
dbVinList.add("C");
dbVinList.add("D");
ediVinList.add("A");
ediVinList.add("C");
ediVinList.add("E");
ediVinList.add("F");
/*ediVinList.add("G");
ediVinList.add("H");
ediVinList.add("I");
ediVinList.add("J");*/
List<String> dbVinListClone = dbVinList;
List<String> ediVinListClone = ediVinList;
boolean flag;
String mismatchVins = null;
if(dbVinListClone.containsAll(ediVinListClone)){
flag = dbVinListClone.removeAll(ediVinListClone);
if(flag){
mismatchVins = getMismatchVins(dbVinListClone);
}
}else{
flag = ediVinListClone.removeAll(dbVinListClone);
if(flag){
mismatchVins = getMismatchVins(ediVinListClone);
}
}
if(mismatchVins != null){
System.out.println("mismatch vins : "+mismatchVins);
}
}
private static String getMismatchVins(List<String> mismatchList){
StringBuilder mismatchVins = new StringBuilder();
int i = 0;
for(String mismatch : mismatchList){
i++;
if(i < mismatchList.size() && i!=5){
mismatchVins.append(mismatch).append(",");
}else{
mismatchVins.append(mismatch);
}
if(i==5){
break;
}
}
String mismatch1;
if(mismatchVins.length() > 100){
mismatch1 = mismatchVins.substring(0, 99);
}else{
mismatch1 = mismatchVins.toString();
}
return mismatch1;
}
}
回答by Peter Lamberg
I have used Guava Sets.difference.
我用过番石榴Sets.difference。
The parameters are sets and not general collections, but a handy way to create sets from any collection (with unique items) is Guava ImmutableSet.copyOf(Iterable).
参数是集合而不是一般集合,但是从任何集合(具有唯一项)创建集合的便捷方法是 Guava ImmutableSet.copyOf(可迭代)。
(I first posted this on a related/dupe question, but I'm copying it here too since I feel it is a good option that is so far missing.)
(我首先在一个相关/重复的问题上发布了这个,但我也在这里复制它,因为我觉得这是一个迄今为止缺少的好选择。)
回答by psycho
THIS WORK ALSO WITH Arraylist
这也适用于 Arraylist
// Create a couple ArrayList objects and populate them
// with some delicious fruits.
ArrayList<String> firstList = new ArrayList<String>() {/**
*
*/
private static final long serialVersionUID = 1L;
{
add("apple");
add("orange");
add("pea");
}};
ArrayList<String> secondList = new ArrayList<String>() {
/**
*
*/
private static final long serialVersionUID = 1L;
{
add("apple");
add("orange");
add("banana");
add("strawberry");
}};
// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);
// Remove all elements in firstList from secondList
secondList.removeAll(firstList);
// Show the "after" list
System.out.println("Result: " + secondList);
回答by jesantana
Although this is a very old question in Java 8 you could do something like
尽管这是 Java 8 中的一个非常古老的问题,但您可以执行以下操作
List<String> a1 = Arrays.asList("2009-05-18", "2009-05-19", "2009-05-21");
List<String> a2 = Arrays.asList("2009-05-18", "2009-05-18", "2009-05-19", "2009-05-19", "2009-05-20", "2009-05-21","2009-05-21", "2009-05-22");
List<String> result = a2.stream().filter(elem -> !a1.contains(elem)).collect(Collectors.toList());
回答by Vlasec
In Java 8 with streams, it's pretty simple actually. EDIT: Can be efficient without streams, see lower.
在带有流的 Java 8 中,实际上非常简单。编辑:可以在没有流的情况下高效,见下。
List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21");
List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19",
"2009-05-20","2009-05-21","2009-05-21","2009-05-22");
List<String> result = listB.stream()
.filter(not(new HashSet<>(listA)::contains))
.collect(Collectors.toList());
Note that the hash set is only created once: The method reference is tied to its contains method. Doing the same with lambda would require having the set in a variable. Making a variable is not a bad idea, especially if you find it unsightly or harder to understand.
请注意,散列集仅创建一次:方法引用与其 contains 方法相关联。对 lambda 做同样的事情需要在变量中设置集合。创建一个变量并不是一个坏主意,尤其是当你觉得它难看或难以理解时。
You can't easily negate the predicatewithout something like this utility method (or explicit cast), as you can't call the negate method reference directly (type inference is needed first).
如果没有这种实用程序方法(或显式转换)之类的东西,您就无法轻松否定谓词,因为您不能直接调用否定方法引用(首先需要类型推断)。
private static <T> Predicate<T> not(Predicate<T> predicate) {
return predicate.negate();
}
If streams had a filterOut
method or something, it would look nicer.
如果流有一个filterOut
方法或其他东西,它看起来会更好。
Also, @Holger gave me an idea. ArrayList
has its removeAll
method optimized for multiple removals, it only rearranges its elements once. However, it uses the contains
method provided by given collection, so we need to optimize that part if listA
is anything but tiny.
另外,@Holger 给了我一个想法。ArrayList
它的removeAll
方法针对多次移除进行了优化,它只重新排列其元素一次。但是,它使用contains
给定集合提供的方法,因此我们需要优化该部分,如果listA
不是很小的话。
With listA
and listB
declared previously, this solution doesn't need Java 8 and it's very efficient.
使用listA
和listB
之前声明,此解决方案不需要 Java 8,并且非常高效。
List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));