【问题标题】:ArrayList's containsAll returning wrong value [closed]ArrayList 的 containsAll 返回错误值
【发布时间】:2025-11-24 23:50:01
【问题描述】:

假设:

a = ["s", "i", "n", "e", "d"];
b = ["s", "e", "n", "d"];

ab 的类型为 List<String>

如何确定b 中的所有字母是否都包含在a 中? -- 不一定按顺序排列(在这种情况下,这是真的,因为[s,e,n,d]ab 中)

使用a.containsAll(b) 并不总是有效!

另一个例子:

a=["b", "a", "z", "z", "z"]
b=["a", "a", "b", "b"]

这里我希望结果为false,因为[a,a,b,b]a 中没有以任何顺序出现,但使用a.containsAll(b) 将返回true

【问题讨论】:

  • 那么为什么不匹配两个列表的大小。如果相等,则选择 containsAll。
  • “修复”是什么意思?如果你想要自己的逻辑,只需编写一个函数来完成它
  • 我想我的意思是有办法改变 containsAll --- 比如 a.containsAll(b, 1) 其中 1 表示它只会扫描每个字母一次
  • 啊我喜欢naveen的回答
  • @PankajKumar 的问题是我也可能有 a=[b,a,n,z,z,z] 和 b=[b,a,n,a,n,a]它会返回真,因为 a 包含 b, a, n

标签: java android string list


【解决方案1】:

试试这个:

private boolean containsAll(List<?> a, List<?> b) {
    // List doesn't support remove(), use ArrayList instead
    ArrayList<Object> x = new ArrayList<Object>();
    ArrayList<Object> y = new ArrayList<Object>();

    x.addAll(a);
    y.addAll(b);
    for (Object o : y) {
        if (!x.remove(o)) // an element in B is not in A!
            return false;
    }
    return true;          // all elements in B are also in A
}

这个想法是从a 中删除b 中的每个字母。当您尝试删除不在a 中的字母时,确认a 不包含b 中的所有字母。

(如果元素存在,remove()将返回true,否则返回false

【讨论】:

    【解决方案2】:

    只需使用 for each
    将整个字符串列表添加到新的字符串变量 并使用 .contains()

    查找一个字符串变量值是否包含另一个字符串
    List<String> a = ["b","a","n"];
    List<String> b = ["b","a","n","a","n","a"];
    
    String newA = null;
    String newB = null;
    
    for(String strA : a) {
      newA += strA;
    }
    for(String strB : b) {
      newB += strB;
    }
    
    if(newA.contains(newB))
      return True;
    else
      return False;
    

    Reference for String .contains()

    【讨论】:

    • 这很棒。谢谢:)
    • 但一个可能的问题:我不想检查字符串是否相等。我想检查一个字符串是否包含在另一个字符串中
    • @user2456977 修改了我的答案,查看它。并按照此示例 URL tutorialspoint.com/java/lang/string_contains.htm
    • 我读到过 String.contains() 但它不能正常工作:它只能按顺序工作。但是如果 a=[s,i,e,n,d] 和 b=[s,e,n,d] String.contains() 将返回 false!即使“发送”包含在“a”中
    • 为您的回答点赞。只需要排序
    【解决方案3】:

    从较大的列表中删除所有未出现在较小列表中的元素并将它们相等。如果它们相等,则较小的列表包含在较大的列表中:

    static List<String> list1 = new ArrayList<String>(){{
        add("b");
        add("a");
        add("n");
        add("z");
        add("z");
        add("z");
        }};
    static List<String> list2 = new ArrayList<String>(){{
        add("b");
        add("a");
        add("n");
        add("a");
        add("n");
        add("a");
    }};
    
    public static void main(String[] args) {
    
        if(deepContains(list1, list2)) 
            System.out.println("List2 is contained in List1"); 
    }
    
    public static boolean deepContains(List<String> one, List<String> two){     
        if (one == null && two == null){
            return true;
        }
    
        if((one == null && two != null) 
          || one != null && two == null){
            return false;
        }
    
        //to avoid messing the order and elements of the lists we will use a copy
        one = new ArrayList<String>(one);
        two = new ArrayList<String>(two);
        //This removes from one all the elements not contained in two
        one.retainAll(two); 
        int a = one.size();
        int b = two.size();
    
        //one has lesser elements than two, for sure two is not contained in one
        if(a < b) return false;
    
        //one has the same number of elements of two, check if they are the same
        if(a == b){
            Collections.sort(one);
            Collections.sort(two);      
            return one.equals(two); 
        }
    
        //one has more elements than two. Remove duplicate elements
        //and check for equality
        Set<String> set1 = new HashSet<String>(one);
        Set<String> set2 = new HashSet<String>(two);
    
        if(set1.size() == set2.size()){
            one = new ArrayList<String>(set1);
            two = new ArrayList<String>(set2);
            Collections.sort(one);
            Collections.sort(two);      
            return one.equals(two); 
        }
        return false;
    }
    

    【讨论】:

    • 你的方法是最好的,除了最后一部分。 set1.size 并不总是等于 set2.size。例如:a=[b,a,n,z,z,z,a,n,a] 和 b=[b,a,n,a,n,a] 应该返回 true,因为香蕉存在于 a 中。它不会在您的方法中返回 true,因为删除重复元素后,banz 将出现在 a 中,而 ban 将出现在 b 中,这将导致它失败。
    • 为方法的第一部分到最后一部分投票
    • Z 不会因为 retainAll 而存在,不是吗?
    • 你是对的,错过了。它应该工作。我试过你的代码,但它对我不起作用。我再看一遍。
    • 你的答案是正确的。它确实有效。抱歉,我今天没喝够咖啡
    【解决方案4】:

    这是适用于任何类型的任何集合的版本:

    private <E> boolean containsAllIncludingDuplicates(Collection<E> container,
            Collection<E> items) {
    
        Set<E> checkedItems = new HashSet<>();
        for (E item : items) {
            if (checkedItems.add(item)
                    && Collections.frequency(container, item) < Collections
                            .frequency(items, item)) {
                return false;
            }
        }
        return true;
    }
    

    Set的使用保证了在item有重复的时候不会多次重复频率检查。

    【讨论】: