简体   繁体   中英

Java StringBuilder.setLength() - is time complexity O(1)?

I'm planning to perform lots of deletes of the last character in StringBuilders. The solution to use sb.setLength(sb.length() - 1); looks good to me. However, since these deletions will be in a loop, I need to know complexity of it.

The way I understand it is that this operation simply decrements some private attribute of my StringBuilder object and does not perform any copying/cloning/duplicating of the characters themselves, thus it is O(1) in time and should work fast.

Am I right?

It's O(1) if the new length is less than the old one, which it is in your case.

The JDK's source code is available online, so you can check it for yourself. Using Java 8 as an example, setLength is implemented in AbstractStringBuilder . It does a few things:

  • errors if the new length < 0
  • ensures that the StringBuilder has enough capacity for the new length (which it will, if you're shortening the length)
  • fills in 0s for the additional length, if you're extending the length (which you're not)
  • sets the this.count field to the length you specify

Putting it all together:

  • If you're shortening the length, this is O(1) — a few quick checks and then a field assignment.
  • If you're increasing the length, but such that the old capacity is still sufficient, then it's O(N) where N is the additional length (for instance, if you had a 100-length builder, then shortened it to 10, and are are now increasing it to 90, then N would be 90-10=80)
  • If you're increasing the length such that the capacity needs to be increased, it's O(N) where N is the new capacity

From the documentation:

Sets the length of the character sequence. The sequence is changed to a new character sequence whose length is specified by the argument. For every nonnegative index k less than newLength, the character at index k in the new character sequence is the same as the character at index k in the old sequence if k is less than the length of the old character sequence; otherwise, it is the null character '\'. In other words, if the newLength argument is less than the current length, the length is changed to the specified length. If the newLength argument is greater than or equal to the current length, sufficient null characters ('\') are appended so that length becomes the newLength argument.

The newLength argument must be greater than or equal to 0.

I would say yes. But I wouldn't see it from the point of view of time complexity. The reason we use StringBuilder instead of String in a loop is because Strings are immutable. Hence a new string object will always be created when we try to change it. When you change the length of a StringBuilder object, no new object is created.

Complexity of setLength differs from operation ( increase or decrease ) complexity of increase operation is not O(1), I think it is O(n), because, in this operation new array will be generated, and each unused byte of stringbuilder with replaced by '\\0' byte

But decrease operation is O(1) complexity , because of that in this operation only count of characters will be changed.

There is source of setLength method in StringBuilder class source file
http://developer.classpath.org/doc/java/lang/StringBuilder-source.html

 225:   public void setLength(int newLength)
 226:   {
 227:     if (newLength < 0)
 228:       throw new StringIndexOutOfBoundsException(newLength);
 229: 
 230:     int valueLength = value.length;
 231: 
 232:     /* Always call ensureCapacity in order to preserve copy-on-write
 233:        semantics.  */
 234:     ensureCapacity(newLength);
 235: 
 236:     if (newLength < valueLength)
 237:       {
 238:         /* If the StringBuilder's value just grew, then we know that
 239:            value is newly allocated and the region between count and
 240:            newLength is filled with '\0'.  */
 241:     count = newLength;
 242:       }
 243:     else
 244:       {
 245:     /* The StringBuilder's value doesn't need to grow.  However,
 246:        we should clear out any cruft that may exist.  */
 247:     while (count < newLength)
 248:           value[count++] = '\0';
 249:       }
 250:   }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM