81

我有两个 ArrayList。

ArrayList A 包含:

['2009-05-18','2009-05-19','2009-05-21']

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']

我必须比较 ArrayList A 和 ArrayList B。结果 ArrayList 应该包含 ArrayList A 中不存在的 List。

ArrayList 结果应该是:

['2009-05-20','2009-05-22']

如何比较?

4

10 回答 10

197

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

上面的代码将产生以下输出:

First List: [apple, orange]
Second List: [apple, orange, banana, strawberry]
Result: [banana, strawberry]
于 2009-05-28T06:14:36.373 回答
20

你已经有了正确的答案。如果您想在列表(集合)之间进行更复杂和有趣的操作,请使用apache commons 集合CollectionUtils)它允许您进行结合/析取,查找交集,检查一个集合是否是另一个集合的子集以及其他好东西。

于 2009-05-28T07:24:32.247 回答
13

在带有流的 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());

请注意,哈希集只创建一次:方法引用与其包含方法相关联。对 lambda 执行相同操作需要将集合放入变量中。制作变量并不是一个坏主意,尤其是当您发现它难看或难以理解时。

没有这种实用方法(或显式转换)之类的东西,你不能轻易地否定谓词,因为你不能直接调用否定方法引用(首先需要类型推断)。

private static <T> Predicate<T> not(Predicate<T> predicate) {
    return predicate.negate();
}

如果流有filterOut方法或其他东西,它会看起来更好。


另外,@Holger 给了我一个想法。ArrayList它的removeAll方法针对多次删除进行了优化,它只重新排列其元素一次。但是,它使用给定集合提供的方法,所以如果不是很小contains的部分,我们需要优化该部分。listA

使用listAandlistB之前声明过,此解决方案不需要 Java 8,而且非常高效。

List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));
于 2017-11-07T17:13:03.220 回答
9

编辑:原始问题未指定语言。我的答案是 C#。

为此,您应该改为使用 HashSet。如果必须使用 ArrayList,可以使用以下扩展方法:

var a = arrayListA.Cast<DateTime>();
var b = arrayListB.Cast<DateTime>();    
var c = b.Except(a);

var arrayListC = new ArrayList(c.ToArray());

使用哈希集...

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
于 2009-05-28T06:08:48.443 回答
8

我用过 Guava Sets.difference

参数是集合而不是一般集合,但是从任何集合(具有唯一项)创建集合的便捷方法是 Guava ImmutableSet.copyOf (Iterable)。

(我首先在一个相关/欺骗问题上发布了这个,但我也在这里复制它,因为我觉得这是一个很好的选择,但到目前为止还没有。)

于 2014-09-02T04:55:26.913 回答
8

尽管这是 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());
于 2016-10-11T12:15:05.180 回答
2

我猜你说的是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;
    }
于 2009-05-28T06:12:22.587 回答
1

您只是在比较字符串。

将 ArrayList A 中的值作为 HashTable A 中的键。
将 ArrayList B 中的值作为 HashTable B 中的键。

然后,对于 HashTable A 中的每个键,如果存在,则将其从 HashTable B 中删除。

HashTable B 中剩下的字符串(键)不是 ArrayList A 中的值。

响应代码请求而添加的 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>();
于 2009-05-28T06:18:24.450 回答
1

嗨使用这个类,这将比较两个列表并准确显示两个列表的不匹配。

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

}
于 2014-03-07T12:32:18.640 回答
1

这也适用于 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);
于 2016-03-07T15:36:04.750 回答