从另一个arrayList中减去一个arrayList

时间:2012-03-29 20:56:57

标签: java

我有两个数组列表,我试图从另一个数组中“减去”一个数组列表。例如,如果我有一个arrayList [1,2,3]并且我试图减去[0,2,4],则得到的arrayList应该是[1,3]。

List<Integer> a = new ArrayList<>(Arrays.asList(1, 2, 3));
List<Integer> b = Arrays.asList(0, 2, 4);
subtract(a,b) // should return [1,3]

这是我的代码。

//returns a new IntSet after subtracting a from b
// .minus().toString()
ArrayList<Integer> minusArray = new ArrayList<Integer>();

    minusArray.addAll(array1);

    for(int i =0; i< minusArray.size(); i++){
        for(int j = 0; j < array2.size(); j++){
            if(minusArray.get(i).equals(array2.get(j))){
                minusArray.remove(i);
                if(i == 0){
                    ;
                }
                else if(j == 0){
                    ;
                }
                else{
                    i = 0;
                    j = 0;
                }
            }
            else{}
        }
    }

return minusArray;

我的代码在某些情况下有效,例如arrayList1 = [4,6]arrayList2 = [6]它会给我[4]的结果。但是如果我尝试[1,2,4][0,4,8]

之类的话

我得到了这个例外:

java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at IntSet.minus(IntSet.java:119)
    at IntSetDriver.main(IntSetDriver.java:62)

这是我提出的代码。我已经完成了测试并且对我来说我认为它应该可行。用户输入这些arrayLists并且它们是预先排序的,我也不知道Hash或big-O。

ArrayList<Integer> minusArray = new ArrayList<Integer>();

    minusArray.addAll(array1);

    for(int i =0; i< minusArray.size(); i++){
        for(int j = 0; j < array2.size(); j++){
            if(minusArray.get(i).equals(array2.get(j))){
                minusArray.remove(i);
            }
            else{}
        }
    }

return minusArray;

9 个答案:

答案 0 :(得分:35)

是否有某些原因你不能简单地使用List.removeAll(List)?

    List<Integer> one = new ArrayList<Integer>();
    one.add(1);
    one.add(2);
    one.add(3);
    List<Integer> two = new ArrayList<Integer>();
    two.add(0);
    two.add(2);
    two.add(4);
    one.removeAll(two);
    System.out.println(one);

    result: "[1, 3]"

答案 1 :(得分:31)

尝试使用org.apache.commons.collections.CollectionUtils类的减法方法。

返回包含-b的新Collection。返回集合中每个元素e的基数将是e的基数,减去b中的e的基数,或者为零,以较大者为准。

CollectionUtils.subtract(java.util.Collection a,java.util.Collection b)

来自Apache Commons Collections

答案 2 :(得分:9)

如果您打算使用 Java8 ,您也可以使用流:

List<Integer> list1 =  Arrays.asList(1, 2, 3);
List<Integer> list2 =  Arrays.asList(1, 2, 4, 5);
List<Integer> diff = list1.stream()
                          .filter(e -> !list2.contains(e))
                          .collect (Collectors.toList()); // (3)

此答案不会操纵原始列表,如果是这样,我们可以使用remove。我们也可以使用forEachIterator中的默认方法)或使用过滤器进行流式传输。

答案 3 :(得分:7)

使用索引遍历minusArray是执行此操作的一种方法,但我建议您使用contains(Object)方法,这样您就可以使用remove(Object) array2的元素。

当然,总有removeAll(Collection)可以完成你需要的一切......

答案 4 :(得分:5)

您可以使用org.apache.commons.collections.ListUtils并在一行中创建您想要的所有内容=)

List resultList = ListUtils.subtract(list, list2);

答案 5 :(得分:3)

您的问题是,在您的minusArray.remove(...)调用中,您可能会缩小minusArray的大小。要解决此问题,请从array.size() - 1开始,然后向后计数到0

检查 - 即使这样也无法修复它。您需要颠倒循环的顺序

答案 6 :(得分:2)

我猜你得到了范围问题,因为你已经删除了一个改变内循环所需内容的元素(我知道在处理普通列表和集合时会出现这个问题)。

过去我必须做的就是创建一个需要删除的项目列表(即原始列表中的项目列表)。迭代这个新列表并直接消除原始列表的元素,而不必让迭代器移动它。

答案 7 :(得分:2)

  

如果removeAll() 不是您想要的,请尝试此答案。例如如果您对Calculating difference of two lists with duplicates

等感兴趣

<强>减法(A,B)

b.forEach((i)->a.remove(i));

a现在包含

[1, 3]

这是关于如何实现减法的suggestion of Guava implementors

  

“创建一个包含a的ArrayList,然后为b中的每个元素调用remove。”

其行为类似于this implementation used in Apache commons

与removeAll()

的区别
[1,2,2,3].removeAll([1,2,3]) //is empty
[1,2,3].forEach((i)->[1,2,2,3].remove(i)); //a is [2] 

答案 8 :(得分:1)

我的参数化解决方案将是:

<T> ArrayList<T> subtract(ArrayList<T> alpha, ArrayList<T> beta) {
    ArrayList<T> gamma = new ArrayList<T>();
    alpha.forEach(n -> {if (!beta.contains(n)) gamma.add(n); });
    return gamma;
}