我打算在StringBuilders中执行大量删除最后一个字符的操作。使用sb.setLength(sb.length() - 1);
的解决方案对我来说很好。但是,由于这些删除将处于循环中,我需要知道它的复杂性。
我理解的方式是这个操作只是减少了我的StringBuilder对象的一些私有属性,并且没有对字符本身进行任何复制/克隆/复制,因此它在时间上是O(1)并且应该快速工作。
我是对的吗?
答案 0 :(得分:8)
如果新长度小于旧长度,那就是O(1),这是你的情况。
JDK的源代码可在线获取,因此您可以自行查看。以Java 8为例,setLength
在AbstractStringBuilder
中实现。它做了一些事情:
this.count
字段设置为您指定的长度全部放在一起:
答案 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: }