如何检查一个字符串数组列表是否包含另一个字符串数组列表的子字符串?

时间:2018-09-27 12:51:59

标签: java string lambda collections java-8

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

是否可以检查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;
}

我试图找到lambda解决方案,但我没有。我发现的所有方法都检查String#equals,而不检查String#contains

最好有这样的东西:

CollectionsUtils.containsAny(actualList, exptectedList);

但是它使用String#equals而不是String#contains比较字符串。

编辑:

基于问题:如果来自actualList的所有子字符串都是ExpectedList的一部分,我想获取TRUE。 下面凯文的解决方案对我有用。

4 个答案:

答案 0 :(得分:11)

怎么样呢?

i

Try it online.

  • list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2))) 将检查所有内容是否为allMatch
  • true将检查是否至少有一个是anyMatch

这里有一些Java 7样式类似的东西,没有lambda和流,以便更好地了解发生了什么:

true

Try it online.


如果您更愿意使用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; ,则可以在代码的其他地方重用,您可以随时自己做一个:

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
  }
}

Try it online.

答案 1 :(得分:3)

我99%的确定您不是在寻找hasAny之类的最受支持的答案,而是要查看expectedList中的所有内容是否包含在actualList中的任何字符串中。为此,首先创建一个Set及其工作将是有益的(因为contains对于O(1)HashSet,而对于{{1}是O(n) }}。

现在考虑一下,由于您只需要List,因此可以拆分contains并从中创建唯一的单词:

actualList

答案 2 :(得分:0)

public static boolean containsAny(List<String> actualList, List<String> expectedList) {
    final Pattern words = Pattern.compile("\\s+");
    return actualList.stream()
                     .flatMap(words::splitAsStream)
                     .distinct()
//                     .allMatch(expectedList::contains)
                     .anyMatch(expectedList::contains);
}

答案 3 :(得分:0)

凯文答案是更好的答案,但另一种方法是重写Wrapper对象的equals方法。

import org.springframework.util.CollectionUtils;

class Holder {
    public String obj;

    public Holder(String obj) {
        this.obj = obj;
    }

    @Override
    public boolean equals(Object holder) {
        if (!(holder instanceof Holder))
            return false;

        Holder newH = ((Holder) holder);

        if (newH == null || newH.obj == null || obj == null)
            return false;

        return obj.contains(newH.obj) || newH.obj.contains(obj);  //actually it's should be one directed.
    }
}

CollectionUtils.containsAny(
            actual.stream().map(Holder::new).collect(Collectors.toList()),
            expected.stream().map(Holder::new).collect(Collectors.toList())
    );
相关问题