【问题标题】:StringBuilder - Append 2 char's or 1 StringStringBuilder - 附加 2 个字符或 1 个字符串
【发布时间】:2020-04-01 11:17:05
【问题描述】:

使用 StringBuilder 时,我经常使用 StringBuilder#append(char) 两次而不是 StringBuilder#append(String) 将 2 个字符值附加到 StringBuilder。

即:

StringBuilder builder = new StringBuilder();

builder.append(' ').append('t'); // would append(" t") work better here?
return builder.toString();

我想知道:

  • 哪种方法在性能方面更好
  • 哪种方法更常见以及为什么

我已经阅读了Using character instead of String for single-character values in StringBuffer append,但它没有回答我的问题。

那个问题与附加单个字符 (append('c')) 是否比单个字符串 (append("c")) 更好。我已经明白为什么附加单个字符优于单个字符串,但我不知道附加两个字符的字符串 (append("ab")) 是否优于附加每个字符两次 (append('a').append('b'))。

【问题讨论】:

  • 很难预测,因为您的代码和 CPU 之间存在 JVM HotSpot。您的代码可能会被优化。这就是为什么最好考虑可读性而不是性能。

标签: java string stringbuilder


【解决方案1】:

在我的测试中,它们似乎都花费了大约相同的时间,但是附加一个字符串可能会稍微慢一些(可能是 10 纳秒左右) 但是,附加字符串更受欢迎,因为它更易于使用/理解。

【讨论】:

    【解决方案2】:

    弄清楚这个真的很有趣。 众所周知,数组速度很快,内部 String 使用字符数组来存储值。

    在内部这两个方法称为super.append(XXX)AbstractStringBuilderclass 的方法。 如果你在 AbstractStringBuilder 中看到了用于 String 和 CharSeq 的 append 代码

    public AbstractStringBuilder append(String str) {
            if (str == null) str = "null";
            int len = str.length();
            ensureCapacityInternal(count + len);
            str.getChars(0, len, value, count);
            count += len;
            return this;
        }
    public AbstractStringBuilder append(CharSequence s, int start, int end) {
            if (s == null)
                s = "null";
            if ((start < 0) || (start > end) || (end > s.length()))
                throw new IndexOutOfBoundsException(
                    "start " + start + ", end " + end + ", s.length() "
                    + s.length());
            int len = end - start;
            ensureCapacityInternal(count + len);
            for (int i = start, j = count; i < end; i++, j++)
                value[j] = s.charAt(i);
            count += len;
            return this;
        }
    

    这些是调用 append 方法时内部调用的方法。 这两个方法都调用ensureCapacityInternal 方法来展开数组。所以让我们保持这个方法调用不变。

    现在,主要区别在于下一行代码。 带有 String args 的方法调用 getChars 方法。它在内部调用System.arraycopy 方法,它是本机方法,我们无法预测该方法的复杂性。它基于 OS/JVM。

    CharSeq 方法使用 for loop 直到输入 charSequence 的长度。 for (int i = start, j = count; i < end; i++, j++) value[j] = s.charAt(i); 即它的复杂性取决于输入的长度。

    在我学习的过程中,其他与 System.arraycopy 方法相关的帖子。他们都说这比通过循环复制数组有效。即使在Effective Java Programing 书中。

    所以最后的意见,我建议如果输入的长度很小,那么只使用 CharSequence。为什么要为小长度的字符串浪费 JVM。

    如果您有像语句这样的长字符串,那么请使用 String args 的方法。另外,请记住在这种情况下空间复杂度会增加。即字符串是不可变的,每次在池中创建更多字符串。 String.valueof(), (String)obj 是示例。

    编辑:

    public AbstractStringBuilder append(char c) { ensureCapacityInternal(count + 1); value[count++] = c; return this; } 
    

    args 为 char 时使用此方法。 似乎是这样。它比其他人更快。 因为在 char 的 count++ 索引处赋值。该方法只包含system.arraycopy方法,在其他所有保证容量的方法中都是通用的。

    希望这会有所帮助。 :)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-07
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多