从另一个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
的意图。 我们也可以使用forEach
( Iterator
默认方法)或带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]