我有两个数组列表,我试图从另一个数组中“减去”一个数组列表。例如,如果我有一个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;
答案 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)
答案 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
。我们也可以使用forEach
(Iterator
中的默认方法)或使用过滤器进行流式传输。
答案 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;
}