【发布时间】:2014-07-16 02:24:29
【问题描述】:
我在面试中遇到了一个问题,要写一个方法来检查相似词,而不考虑字符大小写。
我通过使用每对字符的 ASCII 值的差异来回答它。但是在家里,当我在 String.class 中进行它的实际实现时,我感到很不安 - 为什么它是这样实现的!
我试图在内置方法和我的自定义方法之间进行比较,这种方式-
public class EqualsIgnoreCase {
public static void main(String[] args) {
String str1 = "Srimant @$ Sahu 959s";
String str2 = "sriMaNt @$ sAhu 959s";
System.out.println("Avg millisecs with inbuilt () - " + averageOfTenForInbuilt(str1, str2));
System.out.println("\nAvg millisecs with custom () - " + averageOfTenForCustom(str1, str2));
}
public static int averageOfTenForInbuilt(String str1, String str2) {
int avg = 0;
for (int itr = 0; itr < 10; itr++) {
long start1 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
str1.equalsIgnoreCase(str2);
}
avg += System.currentTimeMillis() - start1;
}
return avg / 10;
}
public static int averageOfTenForCustom(String str1, String str2) {
int avg = 0;
for (int itr = 0; itr < 10; itr++) {
long start2 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
isEqualsIgnoreCase(str1, str2);
}
avg += System.currentTimeMillis() - start2;
}
return avg / 10;
}
public static boolean isEqualsIgnoreCase(String str1, String str2) {
int length = str1.length();
if (str2.length() != length) {
return false;
}
for (int i = 0; i < length; i++) {
char ch1 = str1.charAt(i);
char ch2 = str2.charAt(i);
int val = Math.abs(ch1 - ch2);
if (val != 0) {
if (isInAlphabetsRange(ch1, ch2)) {
if (val != 32) {
return false;
}
} else {
return false;
}
}
}
return true;
}
public static boolean isInAlphabetsRange(char ch1, char ch2) {
return (((ch1 <= 122 && ch1 >= 97) || (ch1 <= 90 && ch1 >= 65)) && ((ch2 <= 122 && ch2 >= 97) || (ch2 <= 90 && ch2 >= 65)));
}
}
输出-
内置 () 的平均毫秒数 - 14
自定义 () 的平均毫秒数 - 5
我发现内置方法正在提高效率,因为有很多检查和方法调用。 这种实施背后有什么具体原因吗?还是我的逻辑中遗漏了什么?
任何建议,将不胜感激!
【问题讨论】:
-
尝试先调用
averageOfTenForCustom,再调用averageOfTenForInbuilt:由于JVM启动,实际结果可能存在差异。 -
小写和大写之间的转换不是一件简单的事情。您只使用基本的 ASCII 拉丁字符(字符距离 32)。但是,当您使用整个 Unicode 集时,问题就相当复杂了。 unicode.org/faq/casemap_charprop.html
-
@sp00m 交替调用它们没有显着差异!我之前已经查过了。
-
还将 0 和 32 的差异视为“匹配”意味着 * (42) 和 J (74) 相等 :-) 所以你会返回匹配 "Jump" 和 "*转"
-
即使在 ASCII 中,您的代码对于不在 Laitn 字母表中的字符也会运行错误。例如,它会为 "0" 和 "P" 或 "0" 和 "\x10' 返回 true
标签: java string performance ignore-case