StringBuffer和摊销

时间:2013-07-04 07:44:36

标签: java arrays arraylist stringbuffer amortized-analysis

ArrayList中,添加操作是摊销操作。因此,在阅读StringBuffer时,我想到了为什么StringBuffer没有摊销。假设我对字符串缓冲区对象使用追加操作,那么它应该能够在其底层数组实现中添加许多字符。但相反,我在源代码中找到了

System.arraycopy(chars, 0, value, count, chars.length);

追加字符串缓冲区的操作。所以我的问题是StringBuffer不能摊销,这样可以减少O(N)的复杂性吗?

4 个答案:

答案 0 :(得分:1)

实际上,StringBufferArrayList的工作方式与您指出的相同,add ArrayList O(1)的操作是ArrayList 摊销

ensureCapacity中,当您添加元素时,您还有一个O(1)方法,如果容量不足,则会分配一个新数组并将数据复制到其中。然而,这种重新分配的操作很少发生,所以你可以认为即使比K超过1次,添加也需要O(n),需要{{1}}。

答案 1 :(得分:1)

在一天结束时,您仍然将N个引用从某个内存位置A移动到其他内存位置B.但是,我确信System.arraycopy能够足够快地执行此操作以使其具有非正式性能来自StringBuffer。但是,这取决于您是append还是insert

回想一下,ArrayList可以通过两种方式执行add:使用单个对象,或者从特定索引点向下移动元素。两者都有不同的表现。

为了解决这个问题,(最终)StringBuffer将调用System.arraycopy()。这个实现实际上是依赖于JVM的(它是本机调用),但可能是非常快。除此之外,没有什么可以真正降低StringBuffer.append()的性能,除了非常要复制的大型非连续内存区域。

ArrayList.add(E element)将花费O(1)时间,但可能会更改为O(N),因为它可能需要增加后备数组以适应其中的更多元素;但是,如果它不必这样做,那么插入时间大约是O(1)(它将元素添加到数组的末尾)。

ArrayList.add(int index, E element)在最好的情况下可能是O(1),但在平均和最差情况下可能是O(N - 指数),因为它必须向下移动到{{1}的元素数量in。

总结一下:

  • E的代码可以看作是amoritized O(N),因为它会复制数组。但是,此操作仍然很快,并且实际上只取决于您移动的数据的大小。

  • StringBuffer.append()的代码不同,在最好的情况下很容易成为一个非定义的O(1),而在最坏的情况下很容易成为O(N)(因为它)对StringBuffer.insert()进行两次调用。在给定点插入元素意味着你必须将其他所有内容都移动,这不是一个便宜的操作,无论你的代码有多快。

我相信,根据您使用的方法,您具有非正式性能。你只需要确定你正在做的操作来判断性能是什么。

答案 2 :(得分:0)

如果您进一步了解源代码:

public AbstractStringBuilder append(char[] str) {
    int len = str.length;
    ensureCapacityInternal(count + len);  // expand array if needed
    System.arraycopy(str, 0, value, count, len); 
    count += len;
    return this;
}

这正是arraylist的作用。

    System.arraycopy(str, 0, value, count, len);

告诉我们从count开始复制到值(从stringBuffer中的当前结束位置开始)。仅复制附加str的长度len

答案 3 :(得分:0)

根据数据结构的大小(ArrayList / StringBuilder长度)和复杂程度混合复杂性,具体取决于输入的大小。

ArrayList的O(1)是指向列表的内容添加单个元素,并按摊销O(1)。显然,在列表中添加n个元素将是n * O(1)。 StringBuilder也是如此。在大多数情况下,添加单个字符是O(1)(除非必须扩展内部数组。但是添加一个char数组需要复制数组的值(实际上,数组的批量复制应该非常快,当然比单个附加更快)字符)。

列表连接的

O(1)可以在使用链表时附加时实现。但结果很容易受到每个连接子列表中的变化的影响,某事。 StringBuilder总是希望避免。此外,链接的字符串列表作为字符串实现将是非常低效的。