我目前正在尝试创建一个方法来确定ArrayList(a2)是否包含ArrayList(a1),因为两个列表都包含重复值(containsAll不会像ArrayList包含重复一样工作值,然后无论值的数量,它都将返回true)
这就是我所拥有的:(我相信它会起作用,但我不能在for循环中使用.remove)
public boolean isSubset(ArrayList<Integer> a1, ArrayList<Integer> a2) {
Integer a1Size= a1.size();
for (Integer integer2:a2){
for (Integer integer1: a1){
if (integer1==integer2){
a1.remove(integer1);
a2.remove(integer2);
if (a1Size==0){
return true;
}
}
}
}
return false;
}
感谢您的帮助。
答案 0 :(得分:1)
如果你想从列表中删除元素,你有两个选择:
另见:
http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-
btw为什么你不覆盖包含方法??
这里你使用简单的对象,如“整数”,当你将使用List&lt; SomeComplexClass&gt; ??
示例使用迭代器删除副本:
List<Integer> list1 = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
List<Integer> listCopy = new ArrayList<>(list1);
Iterator<Integer> iterator1 = listCopy.iterator();
while(iterator1.hasNext()) {
Integer next1 = iterator1.next();
Iterator<Integer> iterator2 = list2.iterator();
while (iterator2.hasNext()) {
Integer next2 = iterator2.next();
if(next1.equals(next2)) list1.remove(next1);
}
}
另见关于迭代器的答案:
Concurrent Modification exception
也不要使用==运算符来比较对象:)而是使用相等的方法
关于使用removeAll()和其他类似的方法:
请记住,许多实现列表接口的类不会覆盖列表接口中的所有方法 - 因此您最终可能会遇到不受支持的操作异常 - 因此在这种情况下我更喜欢“低级”二进制/线性/混合搜索。
并且为了比较复杂类对象,您需要覆盖equal和hashCode方法
如果要删除重复值,只需将arraylist放入HashSet即可。它将基于对象的equals()删除重复项。 - 奥尔加
在Java中,HashMap使用hashCode来定位存储桶。每个存储桶都是驻留在该存储桶中的项目列表。扫描项目,使用等于进行比较。添加项目时,一旦达到一定的负载百分比,就会调整HashMap的大小。
因此,有时它必须与几个项目进行比较,但通常它比O(n)更接近O(1)。
简而言之 - 不需要使用更多资源(内存)和“利用”不必要的类 - 因为随着项目数量的增长,哈希映射“get”方法变得非常昂贵。
hashCode -> put to bucket [if many item in bucket] -> get = linear scan
so what counts in removing items ?
equals和hasCode的复杂性以及使用适当的算法进行迭代
答案 1 :(得分:1)
我认为你的问题最明确的陈述是在你的一条评论中:
是的,例子&#34;例如:[狗,猫,猫,鸟]是匹配的 包含[猫,狗]是假的,但含有[猫,猫,狗]是真的吗?&#34; 正是我想要实现的目标。
实际上,你并不是在寻找&#34;子集&#34;,因为它们不是集合。它们可以包含重复元素。您真正要说的是,您想要查看a1
是否包含a2
的所有元素,并且数量相同。
实现这一目标的一种方法是计算两个列表中的所有元素。我们可以使用这种方法得到这样的计数:
private Map<Integer, Integer> getCounter (List<Integer> list) {
Map<Integer, Integer> counter = new HashMap<>();
for (Integer item : list) {
counter.put (item, counter.containsKey(item) ? counter.get(item) + 1 : 1);
}
return counter;
}
我们将您的方法重命名为containsAllWithCounts()
,并将getCounter()
用作帮助程序。您的方法也会接受List
个对象作为参数,而不是ArrayList
个对象:将参数指定为接口而不是实现是一个好习惯,因此您不必使用{{1类型。
考虑到这一点,我们只是扫描ArrayList
中项目的计数,并在a2
中看到它们是相同的:
a1
如果您愿意,我可以使用Java泛型重写此代码以处理任意类型,而不仅仅是 public boolean containsAllWithCounts(List<Integer> a1, List<Integer> a2) {
Map<Integer,Integer> counterA1 = getCounter(a1);
Map<Integer,Integer> counterA2 = getCounter(a2);
boolean containsAll = true;
for (Map.Entry<Integer, Integer> entry : counterA2.entrySet ()) {
Integer key = entry.getKey();
Integer count = entry.getValue();
containsAll &= counterA1.containsKey(key) && counterA1.get(key).equals(count);
if (!containsAll) break;
}
return containsAll;
}
个对象。此外,可以使用Java 8流(我最初使用的 - 请参阅下面的注释)缩短所有代码。请在评论中告诉我。
答案 2 :(得分:0)
我知道这可能是不成熟的,但是......
无需从两个列表中删除项目,因此,只需从一个列表中删除它
public boolean isSubset(ArrayList<Integer> a1, ArrayList<Integer> a2) {
for(Integer a1Int : a1){
for (int i = 0; i<a2.size();i++) {
if (a2.get(i).equals(a1Int)) {
a2.remove(i);
break;
}
}
if (a2.size()== 0) {
return true;
}
}
return false;
}
答案 3 :(得分:0)
如果要删除重复值,只需将arraylist放入HashSet即可。它将根据对象的equals()删除重复项。