简体   繁体   中英

What is the efficient way to update a String?

Assuming that I need to initiate a String and then update it for a couple a times more, like in this pseudo code:

String s = "first";
if (<some condition>) { s += "second"; }
if (<some condition>) { s += "third"; }
if (<some condition>) { s += "fourth"; }

In case that I have about 4 times in maximum, is it better to use it that way or just simply use StringBuffer/StringBuilder ?

Actually what i'm asking is, in case of which updating times of a String (which is a mutable type) is the efficient way to use the above options?

First, String is not a mutable class. Every time you use += , another object is returned.

Second, unless you use that in a tight loop, it is not very important anyway.

Third, although it may not be a computer science-like approach, if I try to use

    StringBuilder s = new StringBuilder("first");
    s.append( "second" );
    s.append( "third" );
    s.append( "fourth" );

Intellij suggests to replace it with a String, and that suggestion only appears if it is at least as efficient to use a simple String (although it may not be exactly the same thing because of the conditions)

According to Java: String concat vs StringBuilder - optimised, so what should I do? the Java compiler does replace a series of String concatenations with String builders:

public static void main(String[] args) {
    String s = "first";

    s+=" second" ;
    if(args.length >0)
    s+=" third";

    System.out.println("s, = " + s);
}

Using JDK 1.8.0_66 and using javap -c SbTest.class the following output is produced. Although I am not an expert on byte code, it seems that multiple instances of StringBuilder are created ( 3 , 28 ). So as suggested in the linked answers, the compiled code seems to be something like:

    String s = "first";
    s = new StringBuilder().append(s).append(" second") ;
    if(args.length >0)
        s = new StringBuilder().append(s).append(" third") ;

So unless the JIT is optimizing this, it might still be more efficient to use the StringBuilder yourself.

 public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String first
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      10: aload_1
      11: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      14: ldc           #6                  // String  second
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      22: astore_1
      23: aload_0
      24: arraylength
      25: ifle          48
      28: new           #3                  // class java/lang/StringBuilder
      31: dup
      32: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      35: aload_1
      36: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      39: ldc           #8                  // String  third
      41: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      44: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      47: astore_1
      48: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      51: new           #3                  // class java/lang/StringBuilder
      54: dup
      55: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      58: ldc           #10                 // String s, =
      60: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      63: aload_1
      64: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      67: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      70: invokevirtual #11                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      73: return
String s = "first";
if (<some condition>) { s += "second"; }
if (<some condition>) { s += "third"; }
if (<some condition>) { s += "fourth"; }

Is the right approach because the compiler will turn it into a StringBuilder ( JDK 1.6 and above ) That said, the optimization is the same unless you are using it inside a loop.

See this link for more info

If you are working with reasonably sized strings (like the words you have there) using the string class is completely fine, and using a string builder class won't be much faster than using a normal string. You want to replace it when you might be dealing with huge strings (think many many paragraphs) and repeatedly changing them. StringBuilder and StringBuffer should work about the same, but StringBuffer is thread safe, so if you are going to write multithreaded code then use StringBuffer.

The only way to know is to benchmark.

package com.example;

import static org.junit.Assert.*;

import java.time.Duration;
import java.time.Instant;

import org.junit.Test;

public class ExampleTest {

    @Test
    public void test() {
        for (int j = 0; j < 4; j++) {
            Instant start = Instant.now();
            for (int i = 0; i < 10000; i++) {

                // Try various implementations here...
                String s = "first";
                if (true) {
                    s += "second";
                }
                if (true) {
                    s += "third";
                }
                if (true) {
                    s += "fourth";
                }
            }
            System.out.println("Took: " + Duration.between(start, Instant.now()).toMillis() + " millis");
        }
    }

}

If performance turns out not to be an issue then optimise for the human and make it as readable and maintainable as possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM