>想象一下我有以下列表
列表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;
}
}
有没有更短的方法可以做到这一点,也许是 lambda?
将数组转换为小写:
a.stream().map(String::toLowerCase).collect(Collectors.toList());
并使用containsAll
:
b.containsAll(a);
您可以将a
转换为小写String
s 的HashSet
,这将使检查子集的速度更快(因为检查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);
附言,您正在使用术语子集,但实际上您正在检查的不是List
是否是另一个的子集,因为您的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);
您可以使用不区分大小写的比较器创建 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));
}
}