如何检查字符串的ArrayList是否包含另一个字符串ArrayList的子字符串?

Nik*_*iak 6 java string collections lambda java-8

List<String> actualList = Arrays.asList ("mother has chocolate", "father has dog");
List<String> expectedList = Arrays.asList ("mother", "father", "son", "daughter");
Run Code Online (Sandbox Code Playgroud)

有没有办法检查是否expectedList包含字符串的任何子字符串actualList

我找到了一个嵌套的for-each解决方案:

public static boolean hasAny(List<String> actualList, List<String> expectedList) {
    for (String expected: expectedList)
        for (String actual: actualList)
            if (actual.contains(expected))
                return true;

    return false;
}
Run Code Online (Sandbox Code Playgroud)

我试图寻找lambda解决方案,但我不能.我找到的所有方法都检查String#equals而不是String#contains.

有这样的东西会很高兴:

CollectionsUtils.containsAny(actualList, exptectedList);
Run Code Online (Sandbox Code Playgroud)

但它使用String#equalsnot 来比较字符串String#contains.

编辑:

基于问题:如果来自actualList的所有subStrings都是expectedList的一部分,我想得到TRUE.以下凯文的解决方案适合我.

Kev*_*sen 11

这样的事情怎么样:

list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2)))
Run Code Online (Sandbox Code Playgroud)

在线尝试.

  • allMatch 将检查是否一切 true
  • anyMatch 将检查是否至少有一个 true

这里有类似Java 7风格的东西,没有lambdas和流,可以更好地理解发生的事情:

boolean allMatch = true;       // Start allMatch at true
for(String s1 : list1){
  boolean anyMatch = false;    // Start anyMatch at false inside the loop
  for(String s2 : list2){
    anyMatch = s1.contains(s2);// If any contains is true, anyMatch becomes true as well
    if(anyMatch)               // And stop the inner loop as soon as we've found a match
      break;
  }
  allMatch = anyMatch;         // If any anyMatch is false, allMatch becomes false as well
  if(!allMatch)                // And stop the outer loop as soon as we've found a mismatch
    break;
}
return allMatch;
Run Code Online (Sandbox Code Playgroud)

在线尝试.


如果您希望拥有一个CollectionsUtils.containsAny(list1, list2)可以在代码中重复使用的代码,那么您可以自己创建一个:

public final class CollectionsUtil{
  public static boolean containsAny(ArrayList<String> list1, ArrayList<String> list2){
    return list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2)));
    // Or the contents of the Java 7 check-method above if you prefer it
  }

  private CollectionsUtil(){
    // Util class, so it's not initializable
  }
}
Run Code Online (Sandbox Code Playgroud)

然后可以根据需要使用它:

boolean result = CollectionsUtils.containsAny(actualList, expectedList);
Run Code Online (Sandbox Code Playgroud)

在线尝试.

  • @Eugene看起来你确实是对的.我刚刚赞成你的回答.与'O(n)`List复杂度相比,`O(1)`设置复杂度的好方法.正如我在上面的评论中与_Johny Henly_讨论的那样,我不确定OP的意图是什么/不再是......他到目前为止也没有回复评论,他的原始代码已经被其他人修改过了(虽然原始代码段的行为与当前的新代码段有些相似.根据他的原始代码,我确实怀疑你的答案值得在这里勾选. (2认同)