一道String拼接的考题

4 篇文章 0 订阅


题目

When doing string concatenation for many times in a loop, which is the fastest way in terms of executing time:

A) The concat() method of String

B) The + operator of String

CThe append() method of StringBuilder

D) The append() method of StringBuffer


解析

先看concat()的源码

    public String concat(String string) {
        if (string.count > 0 && count > 0) {
            char[] buffer = new char[count + string.count];
            System.arraycopy(value, offset, buffer, 0, count);
            System.arraycopy(string.value, string.offset, buffer, count, string.count);
            return new String(0, buffer.length, buffer);
        }
        return count == 0 ? string : this;
    }


再看“+ ”

public class ConcatString {
    public static void main(String[] args) {
        String a = "a";
        String b = "b";
        String c = a + b;
    }
}

使用javap -c ConcatString.class,看看编译器的做了什么

public class com.nqy.mycode.test.ConcatString {
  public com.nqy.mycode.test.ConcatString();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String a
       2: astore_1      
       3: ldc           #3                  // String b
       5: astore_2      
       6: new           #4                  // class java/lang/StringBuilder
       9: dup           
      10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      13: aload_1       
      14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      17: aload_2       
      18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      24: astore_3      
      25: return        
}

这里,编译器自己做了优化,使用StringBuilder的append来连接,然后返回toString().

但是否如题目所说的,在一个循环中连接多个String,"+"和StringBuidler效率就一样呢?

public class ConcatString {
    public static void main(String[] args) {
        String r = "";
        long s = System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            r+=String.valueOf(i);
        }
        System.out.println(r);
        System.out.println(System.currentTimeMillis() - s);

        StringBuilder sb = new StringBuilder();
        long s2 = System.currentTimeMillis();
        for(int i=0;i<10000;i++){
            sb.append(String.valueOf(i));
        }
        System.out.println(sb.toString());
        System.out.println(System.currentTimeMillis() - s2);
    }
}

执行上面的代码,“+”使用了时间305毫秒,StringBuilder使用了3毫秒。

看编译器是怎么做的

Compiled from "ConcatString.java"
public class com.nqy.mycode.test.ConcatString {
  public com.nqy.mycode.test.ConcatString();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String 
       2: astore_1      
       3: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
       6: lstore_2      
       7: iconst_0      
       8: istore        4
      10: iload         4
      12: sipush        10000
      15: if_icmpge     47
      18: new           #4                  // class java/lang/StringBuilder
      21: dup           
      22: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      25: aload_1       
      26: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      29: iload         4
      31: invokestatic  #7                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      34: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      37: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      40: astore_1      
      41: iinc          4, 1
      44: goto          10
      47: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      50: aload_1       
      51: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      54: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      57: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
      60: lload_2       
      61: lsub          
      62: invokevirtual #11                 // Method java/io/PrintStream.println:(J)V
      65: new           #4                  // class java/lang/StringBuilder
      68: dup           
      69: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      72: astore        4
      74: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
      77: lstore        5
      79: iconst_0      
      80: istore        7
      82: iload         7
      84: sipush        10000
      87: if_icmpge     107
      90: aload         4
      92: iload         7
      94: invokestatic  #7                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
      97: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
     100: pop           
     101: iinc          7, 1
     104: goto          82
     107: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
     110: aload         4
     112: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
     115: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
     118: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
     121: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
     124: lload         5
     126: lsub          
     127: invokevirtual #11                 // Method java/io/PrintStream.println:(J)V
     130: return        
}
每循环一次都创建一个StringBuidler去append,所以开销很大,而直接使用StringBuilder每次循环,只需要append下就可以。

看StringBuilder和StringBuffer的区别

    public synchronized StringBuffer append(char ch) {
        append0(ch);
        return this;
    }

    public StringBuilder append(char c) {
        append0(c);
        return this;
    }

StringBuffer每次append都会检查所否线程安全,所以其效率比StringBuilder低。


所以,答案应是C,使用StringBuilder的append()


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在C++中,可以使用+运算符或append()函数来拼接字符串。引用中的代码中展示了一些字符串拼接的示例。 使用+运算符: string str1 = "ls"; string str2 = "test.c"; string str3 = str1 + " /tmp/"; // str3的值为"ls /tmp/" string str5 = str1 + " append " + "haha"; // str5的值为"ls append haha" 使用append()函数: string tmp = str1 + " append"; string str5 = tmp.append("haha"); // str5的值为"ls append haha" 另外,引用提到了使用push_back()函数来拼接字符串,这是一种高效的方式。 所以,在C++中,可以使用+运算符、append()函数或push_back()函数来进行字符串拼接。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [C++ String拼接](https://blog.csdn.net/u013105549/article/details/52854368)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [C++ string类型字符串拼接](https://blog.csdn.net/neuzhangno/article/details/128686544)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值