How many times have you coded a check for String being null or empty? Countless times, right? I have. We use some ready-to-use classes from open source frameworks or we write our own StringUtils class. More or less they all implement the same thing and it always looks similar to the following code snippet:
String s = ...
if (s == null || s.equals(""))...
or similar to the following, which trims leading and ending whitespaces
String s = ...
if (s == null || s.trim().equals(""))...
Of course you could also do this:
"".equals(s)
which is a case when you do not care if String s is null and you don't have to worry about NPE as if won't happen ("" is never null, whereas s could be). But that's another story.
I have had "extra" warnings turned on in my IDE for couple of days. But today my IDE suprised me when it highlighted
[1] s.equals("")
and suggested that I could optimize it by making it to
[2] s.length() == 0
And guess what?! The IDE was right! I looked at the suggested code briefly, gave it a bit of thought and agreed that it would probably be faster. Method [1] creates a new instance of the String (an empty String, yes I know that all instances of "" would be caught during compilation and optimized and that they all would refer to the same instance). Just to be on the safe side I looked at the source of the String class.
And here is what I found. The length() method returns and integer primitive, which is not calculated with each method call to length(). It is rather a member variable (or constant, as Strings are invariants) of String class that is calculated when new String instance is created. So this method would be super fast.
536 public int length()
537 {
538 return count;
539 }
On the other side, there is the equals() method, which is fast as well, but not as fast as length method. It has to do a check for class, class casting and comparison of count members (that's what length method returns).
684 public boolean equals(Object anObject)
685 {
686 if (! (anObject instanceof String))
687 return false;
688 String str2 = (String) anObject;
689 if (count != str2.count)
690 return false;
691 if (value == str2.value && offset == str2.offset)
692 return true;
693 int i = count;
694 int x = offset;
695 int y = str2.offset;
696 while (--i >= 0)
697 if (value[x++] != str2.value[y++])
698 return false;
699 return true;
700 }
And remember the few important points when it comes to Strings:
- Do not compare Strings with == operator. Unless you want to compare the object references. Use equals() method.
- Do not construct new instances like new String("abc"). Simple "abc" will do, unless you really mean that you need a new instance of String with same value. Read more about How useful is
String(String)
constructor - Do not concatenate Strings in loops using + operator. It's faster to use StringBuffer (or StringBuilder, which is in Tiger and is not synchronized) append() and then toString() methods instead. The plus (+) operator constructs new String object each time.
No comments :
Post a Comment