1 回答
TA贡献2019条经验 获得超9个赞
一般来说,我建议使用Collator强度设置为 的Collator.PRIMARY来比较包含重音符号和不同大小写的字符串(例如,Nvsn和évs e)。不幸的是,Collator没有contains()功能。
所以我们将自己制作。
private static boolean contains(String source, String target) {
if (target.length() > source.length()) {
return false;
}
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
int end = source.length() - target.length() + 1;
for (int i = 0; i < end; i++) {
String sourceSubstring = source.substring(i, i + target.length());
if (collator.compare(sourceSubstring, target) == 0) {
return true;
}
}
return false;
}
这会迭代源字符串,并检查与搜索目标长度相同的每个子字符串是否等于搜索目标(就 Collator 而言)。
例如,假设我们的源字符串是,"This is a Tèst"并且我们正在搜索单词"test"。此方法将迭代每个四个字母的子字符串:
This
his
is i
s is
is
is a
s a
a T
a Tè
Tès
Tèst
一旦找到匹配项就会返回 true。由于强度设置为Collator.PRIMARY,整理器认为"Tèst"和"test"相等,因此我们的方法返回true。
此方法很可能需要进行更多优化,但这应该是一个合理的起点。
编辑RuleBasedCollator:一种可能的优化是利用排序规则键以及and的已知实现细节RuleBasedCollationKey(假设您的项目中有 Google 的 Guava):
private static boolean containsBytes(String source, String target) {
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
byte[] sourceBytes = dropLastFour(collator.getCollationKey(source).toByteArray());
byte[] targetBytes = dropLastFour(collator.getCollationKey(target).toByteArray());
return Bytes.indexOf(sourceBytes, targetBytes) >= 0;
}
private static byte[] dropLastFour(byte[] in) {
return Arrays.copyOf(in, in.length - 4);
}
这是相当脆弱的(可能不适用于所有语言环境),但在我的测试中,它的速度快了 2 倍到 10 倍。
编辑:要支持突出显示,您应该转换contains()为indexOf(),然后使用该信息:
private static int indexOf(String source, String target) {
if (target.length() > source.length()) {
return -1;
}
Collator collator = Collator.getInstance();
collator.setStrength(Collator.PRIMARY);
int end = source.length() - target.length() + 1;
for (int i = 0; i < end; i++) {
String sourceSubstring = source.substring(i, i + target.length());
if (collator.compare(sourceSubstring, target) == 0) {
return i;
}
}
return -1;
}
然后你可以像这样应用它:
String guestWholeName = guest.getGuestFirstName() + " " + guest.getGuestLastName();
int wholeNameIndex = indexOf(guestWholeName, searchText);
if (wholeNameIndex > -1) {
Timber.d("guest name first : guest.getGuestFirstName() %s", guest.getGuestFirstName());
Timber.d("guest name last : guest.getGuestLastName() %s", guest.getGuestLastName());
int endPos = wholeNameIndex + searchText.length();
Spannable spannable = new SpannableString(guestWholeName);
Typeface firstNameFont = Typeface.createFromAsset(context.getAssets(), "fonts/Graphik-Semibold.otf");
spannable.setSpan(new CustomTypefaceSpan("", firstNameFont), wholeNameIndex, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
Objects.requireNonNull(guestName).setText(spannable);
} else {
Objects.requireNonNull(guestName).setText(guestWholeName);
}
添加回答
举报