在什么情况下,String比StringBuffer和StringBuilder更有用

-7 java string

如果stringBuffer和StringBuilder对String很有用,为什么String类不被折旧

Lui*_*oza 5

这是关于每个班级的目的.

Stringclass表示char可以对人类具有特定含义的字符串或集合(数组).

AbstractStringBuilder(这是抽象非public超类的StringBuilderStringBuffer)主要用于构建a的内容String然后生成一个整体String.这是因为String类是不可变的,这意味着对a的任何操作都会String生成一个新String对象,而任何操作都会对同一个引用的状态进行操作StringBuilder或处理StringBuffer,从而节省内存并获得性能.


从可能的重复Q/A 的接受答案:

如果您的字符串不会更改,请使用String类,因为String对象是不可变的.

请注意,这并不意味着您不能String在不知道其特定值或其值是基本串联的结果时定义.这是一个例子:

String name = "Luiggi";
String helloLuiggi = "Hello " + "Luiggi";
String helloName = "Hello " + name;
Run Code Online (Sandbox Code Playgroud)

如果是上述情况:

  • name价值将是"Luiggi".
  • helloLuiggi价值将是"Hello Luiggi".编译器足够聪明,可以理解它"Hello "并且"Luiggi"是字面值String,它们应该生成单个String自动连接,"Hello "并且"Luiggi"不会产生任何性能开销.
  • helloNamevalue将是连接"Hello "name字符串的结果.在这种情况下,编译器将使用StringBuilder幕后为您提高操作性能.

如果您的字符串可以更改(例如:字符串构造中的大量逻辑和操作)并且只能从单个线程访问,则使用a StringBuilder就足够了.

这是完全正确的.这里有一个简单的例子来演示使用普通的性能差异String级联和建设StringStringBuilder使用JUnit的基准:

public class StringVsStringBuilderTest {

    @Rule
    public TestRule benchmarkRun = new BenchmarkRule();

    static final int TIMES = 1000;

    @Test
    public void stringPerformance() {
        String s = "";
        int j = 1;
        for (int i = 0; i < TIMES; i++) {
            s = s + j++;
            if (j == 10) {
                j = 0;
            }
        }
        System.out.println(s);
    }

    @Test
    public void stringBuilderPerformance() {
        StringBuilder sb = new StringBuilder();
        int j = 1;
        for (int i = 0; i < TIMES; i++) {
            sb.append(j++);
            if (j == 10) {
                j = 0;
            }
        }
        System.out.println(sb.toString());
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

StringVsStringBuilderTest.stringPerformance:[测量15轮中的10轮,线程:1(顺序)]
轮:0.00 [+ - 0.00],round.block:0.00 [+ - 0.00],round.gc:0.00 [+ - 0.00], GC.calls:1,GC.time:0.00,time.total:0.05,time.warmup:0.02,time.bench:0.03

StringVsStringBuilderTest.stringBuilderPerformance:[测量15轮中的10轮,线程:1(顺序)]
轮:0.00 [+ - 0.00],round.block:0.00 [+ - 0.00],round.gc:0.00 [+ - 0.00], GC.calls:0,GC.time:0.00,time.total:0.00,time.warmup:0.00,time.bench:0.00

TIMES常量值更改为10000:

StringVsStringBuilderTest.stringPerformance:[测量15轮中的10轮,线程:1(顺序)]
轮:0.04 [+ - 0.02],round.block:0.00 [+ - 0.00],round.gc:0.00 [+ - 0.00], GC.calls:3,GC.time:0.00,time.total:0.66,time.warmup:0.27,time.bench:0.38

StringVsStringBuilderTest.stringBuilderPerformance:[测量15轮中的10轮,线程:1(顺序)]
轮:0.00 [+ - 0.00],round.block:0.00 [+ - 0.00],round.gc:0.00 [+ - 0.00], GC.calls:0,GC.time:0.00,time.total:0.01,time.warmup:0.00,time.bench:0.00

在最后一个示例中,我们可以看到两者之间的时间差异和GC调用.尽管如此,如果你真的不介意0.66秒的时间来连接10000个单值并且有足够的RAM,那么继续使用String连接(但要注意它不是最好的设计而你做错了).

如果您的字符串可以更改,并且将从多个线程访问,请使用StringBuffer因为StringBuffer是同步的,因此您具有线程安全性.

虽然这是真的,看起来你可以使用另一个结构来存储Strings像a BlockingQueue然后使用Strings.