tags:

views:

592

answers:

7

I've been told that code such as:

for (int i=0; i<x.length(); i++) {
    // blah
}

is actually O(n^2) because of the repeated calls to x.length(). Instead I should use:

int l=x.length();
for (int i=0; i<l; i++) {
    // blah
}

Is this true? Is string length stored as a private integer attribute of the String class? Or does length() really walk the whole string just to determine its length?

+21  A: 

No, the length of a java string is O(1) because java's string class stores the length as a field.

The advice you've received is true of C, amongst other languages, but not java. C's strlen walks the char array looking for the end-of-string character. Joel's talked about it on the podcast, but in the context of C.

sblundy
Note that the code will still execute the method call on each iteration (the compiler doesn't know the value won't change). Moving the call outside the loop control will eliminate the method call.Having said that, it isn't likely that will cause much change in the execution time of this loop
Ken Gentle
A modern JIT will probably notice that length() is a simple getter of a final class returning a final primitive value and replace the method call with the int value itself.
sk
sk--I seem to recall seeing a blog that tested the JIT optimization of length() and proved it was true.
James Schek
A: 

According to this, the length is a field of the String object.

JW
A: 

I don't know how well the link will translate, but see the source of String#length. In short, #length() has O(1) complexity because it's just returning a field. This is one of the many advantages of immutable strings.

Daniel Spiewak
Immutability doesn't have anything to do with it. You can have a mutable string class that keeps track of its length, just the same as you can with an immutable string (for instance, StringBuilder). And you can have an Immutable string that doesn't (const char* in C).
Herms
But immutability does guarantee that you only have to calculate the value for length once when the object is created. If the object were mutable it would require a new calculation for every invocation of a mutator method. Pay me now or pay me later as the saying goes.
laz
Strictly speaking, you're both right; but concurrency throws a wrench into the whole affair. Trying to keep an ancillary field updated as the data structure changes asynchronously is essentially impossible, so often length() is computed rather than accessed in mutable String implementations.
Daniel Spiewak
You are absolutely correct and I left that important detail out. Oops!
laz
+6  A: 

Contrary to what has been said so far, there is no guarantee that String.length() is a constant time operation in the number of characters contained in the string. Neither the javadocs for the String class nor the Java Language Specification require String.length to be a constant time operation.

However, in Sun's implementation String.length() is a constant time operation. Ultimately, it's hard to imagine why any implementation would have a non-constant time implementation for this method.

Alexander
+2  A: 

You should be aware that the length() method returns the number of UTF-16 code points, which is not necessarily the same as the number of characters in all cases.

OK, the chances of that actually affecting you are pretty slim, but there's no harm in knowing it.

Marcus Downing
http://java.sun.com/javase/6/docs/api/java/lang/Character.html#unicodeBasically, some characters have to be represented by two char values. Since length() is the size of the char[] array, it might not be the same as the number of characters. But, as sadie said, that's very rare.
Alan Moore
A: 

String stores the length in a separate variable. Since string is immutable, the length will never change. It will need to calculate the length only once when it is created, which happens when memory is allocated for it. Hence its O(1)

Satish
+2  A: 

In the event you didn't know you could write it this way:

for (int i=0, l=x.length(); i<l; i++) {
  //blah
}

It's just slightly cleaner since l's scope is smaller.

Allain Lalonde