【问题标题】:Is this creating 12 string objects?这是创建 12 个字符串对象吗?
【发布时间】:2012-08-29 00:26:59
【问题描述】:

我试图了解下面的代码是否为像“stephan”这样的字符串创建了 12 个对象

public String reverse(String str) {
            if ((null == str) || (str.length()  <= 1)) {
                return str;
            }
            return reverse(str.substring(1)) + str.charAt(0);
        }

这递归地反转一个字符串。我明白它是如何工作的。但我在想,在这种情况下,字符串的长度和通过连接创建的字符串对象的数量之间是否存在关系?

【问题讨论】:

  • substring() 将创建一个字符串对象。 + 将创建另一个。不过,我不知道您所说的与字符串长度的关系是什么意思。
  • 我们只说“按字母数的顺序”。
  • @Marvo - 他的函数是递归的。因此,每次递归调用中每个字符都会发生一次计数
  • substring 不会创建字符串,它会返回原始字符串的视图 - 但是 + 会。
  • 我意识到它是递归的。我指出在代码中创建字符串的位置。输入将确定最终计数。

标签: java


【解决方案1】:

是的,它会创建大量的字符串对象。

对“reverse()”的每次递归调用都会创建 2:

  1. str.substring(1) 将创建一个新的 String 对象

  2. reverse() 调用将为其返回值创建一个新字符串,但我们不会计算它,因为在分析该递归调用时已计算在内(例如,它将是来自下一个 @ 的项目符号点 #3 的字符串987654324@电话)。

  3. 由于Java字符串are immutable,通过“+”添加一个字符将创建一个second字符串对象。

因此,对于长度为 N 的字符串,它将创建 (N-1)*2 个对象(因为 1-char 字符串的反转不会创建新字符串); 所以对于“stephan”的 7 个字符,它将创建 6*2=12 个字符串对象。

【讨论】:

  • 那么返回 char 的 charAt(0) 也会在连接之前转换为字符串吗?
  • 不要忘记为实际连接每个中间结果和下一个字符而创建的 StringBuilders。
  • @Phoenix:不,字符不会转换为字符串,字节码看起来像new StringBuilder().append(string).append(char).toString();
  • @EthanB - StringBuilder 不算作 String 对象,不是吗?请注意,就资源分配而言,它仍然是一个对象;但 OP 明确询问了字符串
  • @DVK 不。它用于连接。 (OP 可能不知道字节码。)
【解决方案2】:

定理:

  • 当字符串长度为N 个字符时,@Phoenix 的reverse 实现将创建(N-1)*3 新对象。

证明(通过归纳):

  • 当str为1个字符时,直接返回。 (1*1)*3 = 0
  • 当 str 的长度为 N 个字符时:
    • .substring(1) 将创建一个新的String
    • 根据归纳假设,对reverse(...) 的调用将在(N-2)*3 对象创建后返回。
    • 将创建一个新的StringBuilder 来附加字符串和第一个char(您可以通过反编译字节码来查看)。
    • StringBuilder.toString() 将创建一个新的String——这是返回值。
    • 总共创建了3 + (N-2)*3 = (N-2 + 1)*3 = (N-1)*3 个对象。
  • QED。

[编辑] StringBuilders:

  • StringBuilder(扩展 AbstractStringBuilder)有它自己的花哨的步法:
    • 在构造StringBuilder 时,会使用大小为16 的char[] 对其进行初始化。
    • 当您附加的内容超出当前大小时,它会将其丢弃并创建一个大小为 (&lt;old size&gt; + &lt;size of new data&gt; + 1) * 2 的新 char[]
  • 因此,只要您的输入字符串大于 16 个字符,您的 StringBuilder 容量就基本上是您需要的 2 倍。 (当输入字符串的大小较小时,char[] 会比您需要的多。)
  • 考虑到Strings 本质上是char[]s(有几个ints 是很好的衡量标准),您实际上在每一步都使用了char[]s 中子字符串长度的4 倍。 :(

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 2015-09-08
    • 2014-11-22
    • 2020-11-28
    • 2015-10-14
    相关资源
    最近更新 更多