代码之家  ›  专栏  ›  技术社区  ›  Julius Häger

StringBuilder insert使用字符串是否有原因。价值?

  •  1
  • Julius Häger  · 技术社区  · 7 年前

    在JDK源代码中 AbstractStringBuilder 这个 append(int) 方法的实现方式不会分配不必要的内存(直接写入内部 char[] 使用 Integer.getChars )。

    但是 insert 使用 String.valueOf 它返回一个新字符串,然后将该数据复制到数组中。正在创建垃圾字符串。

    不是 StringBuilder 减轻串联字符串的垃圾影响。以及 插入 实施起来似乎微不足道。那为什么不是呢?

    Oracle JDK和OpenJDK似乎都是这样。甚至在 javadoc :

    总体效果就像第二个参数被方法string转换为字符串一样。valueOf(int),然后将该字符串的字符插入到指定偏移量处的字符序列中。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Holger    7 年前

    如果你比较 insert(int,int) 和另一个 insert 方法,您将认识到实现方法是保持简单,通过让单个 insert(String) 方法完成所有实际工作。

    在软件开发中,这是一种合理的方法,首先创建一个直接的通用实现来处理所有情况,然后使用实际应用程序进行评测&在场景中,找到创建一个专门的、也许不是那么简单的优化版本有好处的地方。似乎没有搜索到可以使用相同优化实现的其他地方。考虑到之前的测量显然没有显示 插入(int,int) 作为一个重要的热点,这没有坏处。

    要评估情况,重要的是要了解,不是临时对象的数量会重复 String.concat 昂贵的过度创建临时对象可能会给火焰火上浇油,因此如果有一个简单的选择,仍然值得避免。但问题是 一串康卡特 调用是指创建每个临时字符串实例意味着复制组成字符串内容的整个字符数据。更多 concat 调用字符串构建所做的操作,就越接近二次时间复杂度。

    这个 StringBuilder 通过使用可变缓冲区解决此问题。当容量耗尽时,仍会复制它,但通过使用一个因子来确定新容量,总体时间复杂度保持线性。实施 插入 不会改变这一基本原则。临时 String 实例只会导致右侧的复制,因此它只引入一个常数因子2,而不是改变时间复杂度。

    但不要忘记这一点 插入 原则上承载缓冲区后续字符数据的复制。如果重复在缓冲区的开头插入,无论底层实现的优化程度如何,都会朝着二次时间复杂度的方向发展。因此,如果你做得太过分,那么二的因子将变得微不足道。