我们已经delete()
在StringBuffer
. 为什么我们需要deleteCharAt()
?不会deleteCharAt(n)
做delete(n, n+1)
同样的事情吗?
6 回答
查看源代码表明 delete() 没有使用 deleteCharAt() ,反之亦然。我注意到一个小的区别:如果索引不在范围内,deleteCharAt 将抛出异常,而当第二个参数传递字符串长度时,delete 将默认为字符串的长度。
但是对字符串缓冲区内容的影响是一样的。
一个可能的原因是简单。为什么需要两个参数来删除单个字符?
另一种可能性是delete()
根据 , 实现的deleteCharAt()
,deleteCharAt()
因此无论如何都需要存在并且本身很有用,因此它被简单地宣布为 public。但是可以查看源代码,发现这里不是这种情况。但这是许多其他 Java 类中的常见模式。
第三种可能性是,因为该方法能够假设它正在删除单个字符,deleteCharAt()
所以可以以比更通用的delete()
. 然而,源代码再次排除了这个选项。两种方法都解析为几乎相同的System.arraycopy()
.
因此,鉴于此,我对第一个选项投了赞成票。这样做只是为了通过将程序员需要提供的参数数量从 2 个减少到 1 个来简化删除单个字符的相对常见用例。
您可能会获得相同的结果,但实际上,这里存在一些效率问题......
对于在给定索引处删除,对该索引进行一次简单检查就足够了,而在删除一系列索引时还需要进行几次检查。
你自己看 :
public AbstractStringBuilder delete(int start, int end)
{
if (start < 0)
throw new StringIndexOutOfBoundsException(start);
if (end > count)
end = count;
if (start > end)
throw new StringIndexOutOfBoundsException();
int len = end - start;
if (len > 0) {
System.arraycopy(value, start+len, value, start, count-end);
count -= len;
}
return this;
}
相比:
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;
}
因此,如果您只需要删除一个字符,您最好使用 deleteCharAt 并保存一些检查。然而,如果你想删除超过 1 个连续的字符,最好使用 delete 以便只调用一次 arraycopy 并且每次调用 deleteCharAt 时都不会重复检查:)
有一个区别*:
如果n
是文本的长度,buffer.length()
那么deleteCharAt(n)
将抛出一个 StringIndexOutOfBoundsException,而delete(n, n+1)
什么也不做 - 没有异常,没有被删除。
对于更大的值n
,两者都会抛出异常。
IMO 最好使用它,deleteCharAt
因为它正是您想要做的。使用delete
有点难以理解。
(并对delete
附加索引进行更多检查)
* Java 1.6
不同之处在于函数的实现 DeleteAt 是一条语句,例如从列表中删除 list.remove(index) delete 接受两个参数,并从起始索引开始循环并调用删除函数,直到第二个参数。
在 的实现中可以利用一些效率deleteCharAt
,因为该方法知道它正在删除一个字符。
相反,删除其中的一系列字符delete(n, m)
可能需要更复杂的执行路径,这些执行路径必然更昂贵,因为它们“做得更多”。
虽然delete(n, n+1)
与 具有相同的效果deleteCharAt(n)
,但 deleteCharAt 可能会更快。(优化器可以将一个转换为另一个!)。肯定不会慢。