Java:查看ArrayList是否包含具有重复值的ArrayList

时间:2016-08-22 00:41:41

标签: java arraylist

我目前正在尝试创建一个方法来确定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;
}

感谢您的帮助。

4 个答案:

答案 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()删除重复项。