Java CharAt() 和 deleteCharAt() 性能String.charAt :StringBuffer.charAt :StringBuilder.charAt :StringBuffer.deleteCharAt :StringBuilder.deleteCharAt :AbstractStringBuilder.deleteCharAt :

我一直在想Java中函数的实现,它的复杂性是什么?另外,在?charAtString/StringBuilder/StringBufferdeleteCharAt()StringBuffer/StringBuilder


答案 1

对于 、 和 ,是一个常数时间运算。StringStringBufferStringBuildercharAt()

For 和 是线性时间运算。StringBufferStringBuilderdeleteCharAt()

StringBuffer并具有非常相似的性能特征。主要区别在于前者是(线程安全也是如此),而后者不是。StringBuildersynchronized


答案 2

让我们依次看一下这些方法中每个方法的相应实际java实现(仅相关代码)。这本身将回答他们的效率。

String.charAt :

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

正如我们所看到的,它只是一个单数组访问,这是一个恒定的时间操作。

StringBuffer.charAt :

public synchronized char charAt(int index) {
  if ((index < 0) || (index >= count))
    throw new StringIndexOutOfBoundsException(index);
  return value[index];
}

同样,单阵列访问,所以是一个恒定的时间操作。

StringBuilder.charAt :

public char charAt(int index) {
    if ((index < 0) || (index >= count))
        throw new StringIndexOutOfBoundsException(index);
    return value[index];
}

同样,单阵列访问,所以是一个恒定的时间操作。尽管这三种方法看起来都相同,但也有一些细微的差异。例如,只有 StringBuffer.charAt 方法是同步的,而不是其他方法。同样,如果 String.charAt 的检查略有不同(猜猜为什么?)。仔细观察这些方法实现本身,它们之间还有其他细微的差异。

现在,让我们看一下 deleteCharAt 的实现。

字符串没有 deleteCharAt 方法。原因可能是它是一个不可变的对象。因此,公开一个明确指示此方法修改对象的API可能不是一个好主意。

StringBuffer和StringBuilder都是AbstractStringBuilder的子类。这两个类的 deleteCharAt 方法将实现委托给其父类本身。

StringBuffer.deleteCharAt :

  public synchronized StringBuffer deleteCharAt(int index) {
        super.deleteCharAt(index);
        return this;
    }

StringBuilder.deleteCharAt :

 public StringBuilder deleteCharAt(int index) {
        super.deleteCharAt(index);
        return this;
    }

AbstractStringBuilder.deleteCharAt :

  public AbstractStringBuilder deleteCharAt(int index) {
        if ((index < 0) || (index >= count))
            throw new StringIndexOutOfBoundsException(index);
        System.arraycopy(value, index+1, value, index, count-index-1);
        count--;
        return this;
    }

仔细观察 AbstractStringBuilder.deleteCharAt 方法,就会发现它实际上是在调用 System.arraycopy。在最坏的情况下,这可能是O(N)。所以deleteChatAt方法是O(N)时间复杂度。