[英]How do I check two collections for equality ignoring case?
I want to treat lowercase and uppercase values the same, and make sure two collections are equal (does not have to be sorted) 我想将小写和大写值相同,并确保两个集合相等(不必排序)
This is my implementation: 这是我的实现:
private boolean stringCollectionEqualsIgnoreCase(Collection<String> c1, Collection<String> c2)
{
Set<String> s1 = new HashSet<>();
c1.forEach(i -> s1.add(i.toLowerCase()));
Set<String> s2 = new HashSet<>();
c2.forEach(i -> s2.add(i.toLowerCase()));
return s1.size() == s2.size() && s2.containsAll(s1);
}
Is there an easier way to do this? 有没有更简单的方法可以做到这一点? Or is it better to have my own method
还是拥有自己的方法更好
Your actual solution is very acceptable. 您的实际解决方案是可以接受的。 It is clear enough and it should have a overall good performance.
很清楚,它应该具有总体良好的性能。
You should use Set.equals()
instead of Set.containsAll()
. 您应该使用
Set.equals()
而不是Set.containsAll()
。 It makes the same things but it spare you from comparing the size as optimization. 它具有相同的作用,但是可以避免将大小作为优化进行比较。
1) A stream version of your code could be : 1)您的代码的流版本可能是:
private boolean stringCollectionEqualsIgnoreCase(Collection<String> c1, Collection<String> c2) {
return c1.stream()
.map(String::toLowerCase)
.collect(toSet())
.equals(c2.stream()
.map(String::toLowerCase)
.collect(toSet()));
}
2) Here is a second alternative with Treeset
. 2)这是
Treeset
的第二种选择。
I am not sure that it is easier but it avoids explicit loops and makes the logic more explicit as factored out : 我不确定是否更容易,但是它避免了显式循环,并且使逻辑变得更加明确:
private boolean stringCollectionEqualsIgnoreCase(Collection<String> c1, Collection<String> c2)
{
Comparator<String> comp = Comparator.comparing(String::toLowerCase);
Set<String> s1 = new TreeSet<>(comp);
Set<String> s2 = new TreeSet<>(comp);
s1.addAll(c1);
s2.addAll(c2);
return s1.equals(s2);
}
Note that it removes duplicates according to the comparator. 请注意,它会根据比较器删除重复项。 That means that it sorts.
这意味着它可以排序。 So it could be slower or faster than your actual solution according to the cases.
因此,根据情况,它可能比您的实际解决方案慢或快。 Of course for small
Set
s to compare, it doesn't matter. 当然,要比较小的
Set
没关系。
Since there is no native library providing this, I think you'll always have to do some workaround, but the following could be an elegant solution without having to change your existing collections. 由于没有本机库提供此功能,因此我认为您总是必须采取一些变通方法,但是以下方法可能是一种优雅的解决方案,而无需更改您现有的馆藏。
public boolean containsAllIgnoreCase(Collection<String> var1, Collection<String> var2) {
return var1.stream()
.map(String::toLowerCase)
.collect(toList())
.containsAll(var2.stream()
.map(String::toLowerCase)
.collect(toList());
}
Or even more easier to read 甚至更容易阅读
public List<String> toLowerCaseList(Collection<String> var) {
return var.stream().map(String::toLowerCase).toList();
}
public boolean containsAllIgnoreCase(Collection<String> var1, Collection<String> var2) {
return toLowerCaseList(var1).containsAll(toLowerCaseList(var2));
}
If an implementation that works with Set
s is enough, you could store your unique elements in a TreeSet
with a special case-insensitive comparator: 如果可以使用
Set
的实现就足够了,则可以使用不区分大小写的特殊比较器将唯一元素存储在TreeSet
:
Set<String> uniqueStrings = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
This way you can make the comparison simply with uniqueStrings.equals(anotherTreeSet)
. 这样,您可以简单地使用
uniqueStrings.equals(anotherTreeSet)
进行比较。 It's a bit of a hack, I have to admit. 我不得不承认,这有点骇人听闻。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.