I encountered a question in interview to write a method to check for similar words irrespective of character cases.
I answered it by using the difference of ASCII value for each pair of characters. But at home, when I went through the actual implementation of it in String.class, I get disturbed - Why is it implemented that way!
I tried to draw a comparison between inbuilt and my custom method, this way-
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))); } }
Output-
Avg millisecs with inbuilt () - 14
Avg millisecs with custom () - 5
I found that the inbuilt method is hitting efficiency, as because of lots of checks and method calls. Is there any specific reasons behind such an implementation? Or Am I missing something in my logic?
Any suggestions, will be heartily appreciated!
equalsIgnoreCase() is 20–50% faster than the equals(param.
Java String equalsIgnoreCase() Method The equalsIgnoreCase() method compares two strings, ignoring lower case and upper case differences. This method returns true if the strings are equal, and false if not. Tip: Use the compareToIgnoreCase() method to compare two strings lexicographically, ignoring case differences.
Java String equals() and equalsIgnoreCase() Methods example Both of these methods are used for comparing two strings. The only difference between them is that the equals() methods considers the case while equalsIgnoreCase() methods ignores the case during comparison.
Difference between equals() vs equalsIgnoreCase() in JavaUse equals() in Java to check for equality between two strings. Use equalsIgnoreCase() in Java to check for equality between two strings ignoring the case.
Your routine only handles ASCII characters. The system one handles all unicode characters.
Consider following example:
public class Test { public static void main(String[] args) { System.out.println((int) 'ě'); // => 283 System.out.println((int) 'Ě'); // => 282 } }
Your method is incorrect in many ways. For instance, it considers "!" equal to "B", "B" equal to "1", but "!" not equal to "1" (so it isn't transitive as we would expect an equals method to be).
Yes, it is quite easy to write an incorrect implementation for that method that is both faster and simpler. A fair challenge would be to write a correct one, i.e. that correctly handles all arguments the JDK implementation does.
You might also wish to look at How do I write a correct micro-benchmark in Java? to get more reliable performance measurements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With