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。 下面凯文的解决方案对我有用。
答案 0 :(得分:11)
怎么样呢?
i
list1.stream().allMatch(s1 -> list2.stream().anyMatch(s2 -> s1.contains(s2)))
将检查所有内容是否为allMatch
true
将检查是否至少有一个是anyMatch
这里有一些Java 7样式类似的东西,没有lambda和流,以便更好地了解发生了什么:
true
如果您更愿意使用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
}
}
答案 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())
);