想象一下,我有以下列表
列出a
- ("One", "Two", "Three", "Four", "Five")
列出b
- ("oNe", "two", "THREE")
我想将b
视为a
的一个子集(忽略此情况)。
现在我正在使用循环和一些像这样的lambda
boolean subset = true;
for(String bWord : b) {
if(!a.stream().anyMatch(aWord -> aWord.equalsIgnoreCase(bWord))) {
subset = false;
break;
}
}
使用lambdas有没有更短的方法呢?
答案 0 :(得分:6)
将数组转换为小写:
a.stream().map(String::toLowerCase).collect(Collectors.toList());
并使用containsAll
:
b.containsAll(a);
答案 1 :(得分:4)
您可以将a
转换为HashSet
小写String
,这样可以更快地检查子集(因为它需要花费很长时间来检查是否有任何元素b
属于aset
,而不是检查包含在List
中所需的线性时间):
Set<String> aset = a.stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
boolean subset = b.stream().map(String::toLowerCase).allMatch(aset::contains);
PS,您使用的是子集一词,但实际上您要检查的不是一个List
是另一个的{strong>子集,由于您的List
不是Set
s,这意味着它们可能包含重复值。首先从Set
开始是更有意义的。
编辑:
如果使用containsAll
似乎更好,至少在两个Set
而不是两个List
上运行它。您将获得线性运行时间而不是二次运行时间:
Set<String> aset = a.stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
Set<String> bset = b.stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
boolean subset = aset.containsAll(bset);
答案 2 :(得分:0)
您可以使用不区分大小写的Comparator
创建TreeSet的子类public class MyStringSet extends TreeSet<String> {
private static class CaseInsensiteStringComparator implements Comparator<String> {
@Override
public int compare(String a, String b) {
return a.toLowerCase().compareTo(b.toLowerCase());
}
}
public MyStringSet() {
super(new CaseInsensiteStringComparator());
}
public MyStringSet(Collection<? extends String> arg0) {
super(new CaseInsensiteStringComparator());
addAll(arg0);
}
public MyStringSet(Comparator<? super String> arg0) {
super(arg0);
}
public MyStringSet(SortedSet<String> arg0) {
super(new CaseInsensiteStringComparator());
addAll(arg0);
}
public static void main(String[] args) {
List<String> b = Arrays.asList("eins", "drei", "zwei");
MyStringSet a = new MyStringSet(Arrays.asList("Vier", "DRei", "zWei", "einS"));
System.out.println(a.containsAll(b));
}
}