从另一个arrayList中减去一个arrayList

我有两个arrayLists,我试图从另一个“减去”一个arrayList。 例如,如果我有一个arrayList [1,2,3]并且我试图减去[0,2,4],结果arrayList应该是[1,3]。

List a = new ArrayList(Arrays.asList(1, 2, 3)); List 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 minusArray = new ArrayList(); 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 minusArray = new ArrayList(); 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; 

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

检查 – 即使这不会修复它。 您需要反转循环的顺序

有什么理由你不能简单地使用List.removeAll(List)?

  List one = new ArrayList(); one.add(1); one.add(2); one.add(3); List two = new ArrayList(); two.add(0); two.add(2); two.add(4); one.removeAll(two); System.out.println(one); result: "[1, 3]" 

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

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

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

来自Apache Commons Collections

使用索引遍历minusArray是一种方法,但我建议您使用contains(Object)方法,这将允许您对array2的特定元素使用remove(Object)

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

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

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

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

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

这个答案不会操纵原始列表,如果这是我们可以使用remove的意图。 我们也可以使用forEachIterator默认方法)或带filter的流。

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

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

如果removeAll() 不是您想要的,请尝试此答案。 例如,如果您对计算带有重复项的两个列表的差异感兴趣

减去(A,B)

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

a现在包含

 [1, 3] 

这遵循了Guava实现者关于如何实现减法的建议

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

其行为类似于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]