String vs StringBuilder vs StringBuffer (Java)

What's the difference among String, StringBuilder and StringBuffer, in Java?

Labs

Lab 1 Append Method

    public static void app(String s){
        s += " world";
    }


    public static void app(StringBuilder s){
        s.append(" world");
    }

    public static void app(StringBuffer s){
        s.append(" world");
    }

    public static void main(String args[]){                
        String string = new String("hello");
        StringBuilder stringBuilder = new StringBuilder("hello");
        StringBuffer stringBuffer = new StringBuffer("hello");

        app(string);
        app(stringBuilder);
        app(stringBuffer);

        System.out.println(string);
        System.out.println(stringBuilder);
        System.out.println(stringBuffer);
    }

Output

hello
hello world
hello world

Explanation

  1. String: String is taken as reference. The string in main() still refers to the old one, which is "hello". Some may say that string is a reference of "hello", after app() the actual value should be changed. However,  s += " world" means, s = s + "world". So s is reasigned, after which, s in method app() refers to a new one, "hello world". But string in main() still refers to the old one, "hello".
  2. StringBuilder: stringBuilder is passed as a reference, which refers to "hello". After app(), the actual value is changed. In app(), if we have s = new StringBuilder("world"), we will get the result, "hello" (same as above).
  3. StringBuffer: same as StringBuilder.

Lab 2 Multiple Thread

    static String string = "";
    static StringBuilder stringBuilder = new StringBuilder();
    static StringBuffer stringBuffer = new StringBuffer();

    public static void main(String args[]) throws InterruptedException {
        T t = new T();
        S s = new S();
        t.start();
        s.start();
        Thread.sleep(50);
        System.out.println("string \t\t\t" + string);
        System.out.println("stringbuffer \t" + stringBuffer);
        System.out.println("stringbuilder \t" + stringBuilder);
    }

    static class T extends Thread{
        @Override
        public void run(){
            for(int i = 0; i < 5; i++){
                for(int j = 0; j < 10; j++) string += "t";
                for(int j = 0; j < 10; j++) stringBuilder.append("t");
                for(int j = 0; j < 10; j++) stringBuffer.append("t");
                try {
                    sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    static class S extends Thread{
        @Override
        public void run(){
            for(int i = 0; i < 5; i++){
                for(int j = 0; j < 10; j++) string += "s";
                for(int j = 0; j < 10; j++) stringBuilder.append("s");
                for(int j = 0; j < 10; j++) stringBuffer.append("s");
                try {
                    sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Output

These codes end in different results.

Sometimes it prints three lines of strings, which could be the same, or not the same.

Sometimes, unexpected hollow squares apper in stringBuilder, as is shown below.

Sometimes, it throws an exception.

Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at java.lang.String.getChars(String.java:826)
	at java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:422)
	at java.lang.StringBuilder.append(StringBuilder.java:136)
	at trash.PlayJava$S.run(Test.java:61)

Explanation

StringBuilder is not thread save class, while StringBuffer is. According to the source code, most of methods in StringBuffer use synchronized key word.


Lab 3 Speed Comparison

    static final int a = 500000;
    static String string = "";
    static StringBuilder stringBuilder = new StringBuilder();
    static StringBuffer stringBuffer = new StringBuffer();

    public static long run(String s){
        long startTime = System.currentTimeMillis();
        for(int i = 0; i < a; i++) s += "s";
        return System.currentTimeMillis() - startTime;
    }

    public static long run(StringBuilder s){
        long startTime = System.currentTimeMillis();
        for(int i = 0; i < a; i++) s.append("s");
        return System.currentTimeMillis() - startTime;
    }

    public static long run(StringBuffer s){
        long startTime = System.currentTimeMillis();
        for(int i = 0; i < a; i++) s.append("s");
        return System.currentTimeMillis() - startTime;
    }

    public static void main(String args[]){
        System.out.println("String: \t\t" + String.valueOf(run(string)));
        System.out.println("StringBuilder: \t" + String.valueOf(run(stringBuilder)));
        System.out.println("StringBuffer: \t" + String.valueOf(run(stringBuffer)));

    }

Output

String: 	88422
StringBuilder: 	12
StringBuffer: 	27

Conclusion & Explanation

Generally, speed: StringBuilder > StringBuffer >> String. So if need to modify a string frequently, better to use StringBuilder (ignoring thread safety) and StringBuffer.

String is immutable, which means once it is created, it cannot be modified. So appending a String object is very time-comsuming.


Lab 4

    public static void main(String args[]){
        String s1 = "hello world",
                s2 = "hello world",
                s3 = new String("hello world");
        StringBuilder strbd1 = new StringBuilder("hello world"),
                strbd2 = new StringBuilder("hello world");
        StringBuffer strbf1 = new StringBuffer("hello world"),
                strbf2 = new StringBuffer("hello world");

        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(strbd1 == strbd2);
        System.out.println(strbf1 == strbf2);
    }

Output

true
false
false
false

Explanation

String is stored in Constant String Pool (an area in heap). In this example, s1 = "hello world" creates an instance in it. The next line, s2 has the same value. In this case, no more instance will be created. Instead, s2 becomes a reference, which refers to "hello world". So s1 and s2 point to same thing. By the way, String is immutable, and every immutable object in Java is thread safe.


Lab 5 Type Conversion

    public static String stringBuffer2String(StringBuffer s){
        return s.toString();
    }

    public static String stringBuilder2String(StringBuilder s){
        return s.toString();
    }

    public static StringBuilder string2StringBuilder(String s){
        return new StringBuilder(s);
    }

    public static StringBuilder stringBuffer2StringBuilder(StringBuffer s){
        return new StringBuilder(s);
    }

    public static StringBuffer string2StringBuffer(String s){
        return new StringBuffer(s);
    }

    public static StringBuffer stringBuilder2StringBuffer(StringBuilder s){
        return new StringBuffer(s);
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值