Java StringBuilder.setLength() - 是时间复杂度O(1)?

时间:2016-01-31 05:35:13

标签: java big-o time-complexity

我打算在StringBuilders中执行大量删除最后一个字符的操作。使用sb.setLength(sb.length() - 1);的解决方案对我来说很好。但是,由于这些删除将处于循环中,我需要知道它的复杂性。

我理解的方式是这个操作只是减少了我的StringBuilder对象的一些私有属性,并且没有对字符本身进行任何复制/克隆/复制,因此它在时间上是O(1)并且应该快速工作。

我是对的吗?

3 个答案:

答案 0 :(得分:8)

如果新长度小于旧长度,那就是O(1),这是你的情况。

JDK的源代码可在线获取,因此您可以自行查看。以Java 8为例,setLengthAbstractStringBuilder中实现。它做了一些事情:

    如果新长度<
  • 错误0
  • 确保StringBuilder具有足够的容量来容纳新长度(如果缩短长度,它将会是这样)
  • 填写额外长度的0,如果你延长了长度(你不是)
  • this.count字段设置为您指定的长度

全部放在一起:

  • 如果缩短长度,则为O(1) - 一些快速检查,然后是字段分配。
  • 如果你增加长度,但旧容量仍然足够,那么它是O(N),其中N是附加长度(例如,如果你有一个100长度的构建器,那么它缩短为10,现在正将它增加到90,然后N将是90-10 = 80)
  • 如果你增加长度使得容量需要增加,那就是O(N),其中N是新容量

答案 1 :(得分:4)

来自文档:

  

设置字符序列的长度。序列将更改为新的字符序列,其长度由参数指定。对于每个小于newLength的非负索引k,如果k小于旧字符序列的长度,则新字符序列中索引k处的字符与旧序列中索引k处的字符相同;否则,它是空字符' \ u0000'。换句话说,如果newLength参数小于当前长度,则长度将更改为指定的长度。   如果newLength参数大于或等于当前长度,则会附加足够的空字符(' \ u0000'),以便length成为newLength参数。

     

newLength参数必须大于或等于0.

我会说是的。但是从时间复杂性的角度来看,我不会看到它。我们在循环中使用StringBuilder而不是String的原因是因为字符串是不可变的。因此,当我们尝试更改它时,将始终创建一个新的字符串对象。更改StringBuilder对象的长度时,不会创建新对象。

答案 2 :(得分:3)

setLength的复杂性与操作(增加或减少)不同 增加操作的复杂性不是O(1),我认为它是O(n),因为,在这个操作中会生成新的数组,而stringbuilder的每个未使用的字节都被' \ 0'字节

但减少操作是O(1)复杂度,因为在此操作中只会改变字符数。

StringBuilder类源文件中有setLength方法的来源 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:   }