-7

if stringBuffer & StringBuilder are much usefull over String, why String class is not depreciated

2 Answers2

5

It is about the purpose of each class.

String class represents a string or a set (array) of chars that can have a specific meaning for humans.

AbstractStringBuilder (which is the abstract non public super class for StringBuilder and StringBuffer) is mainly used to build the contents of a String and then generate a whole String. This is because String class is immutable, which means that any operation on a String generates a new String object, while any operation over StringBuilder or StringBuffer works on the state of the same reference, thus saving memory and gaining performance.


From the accepted answer of the possible duplicate Q/A:

If your string is not going to change use a String class because a String object is immutable.

Note that this doesn't mean you cannot define a String when you don't know its specific value or if its value is the result of a basic concatenation. Here's an example:

String name = "Luiggi";
String helloLuiggi = "Hello " + "Luiggi";
String helloName = "Hello " + name;

In case above:

  • name value will be "Luiggi".
  • helloLuiggi value will be "Hello Luiggi". The compiler is smart enough to understand that "Hello " and "Luiggi" are literal String values and they should generate a single String automatic concatenation of "Hello " and "Luiggi", this doesn't generate any performance overhead.
  • helloName value will be the result of concatenating "Hello " and name strings. In this case, the compiler will use a StringBuilder behind the scenes for you to improve the performance of the operation.

If your string can change (example: lots of logic and operations in the construction of the string) and will only be accessed from a single thread, using a StringBuilder is good enough.

This is completely true. Here's a basic example to demonstrate the difference in performance of using plain String concatenation and building the String from a StringBuilder using JUnit Benchmark:

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());
    }
}

Results:

StringVsStringBuilderTest.stringPerformance: [measured 10 out of 15 rounds, threads: 1 (sequential)]
round: 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: [measured 10 out of 15 rounds, threads: 1 (sequential)]
round: 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

Changing TIMES constant value to 10000:

StringVsStringBuilderTest.stringPerformance: [measured 10 out of 15 rounds, threads: 1 (sequential)]
round: 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: [measured 10 out of 15 rounds, threads: 1 (sequential)]
round: 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

In the last example, we can see the difference in time and GC calls between both. Still, if you don't really mind 0.66 seconds of your time to concatenate 10000 single values and have enough RAM, then continue using String concatenation (but be aware that it is not the best design and you're doing something wrong).

If your string can change, and will be accessed from multiple threads, use a StringBuffer because StringBuffer is synchronous so you have thread-safety.

While this is true, looks like you could use another structure to store the Strings like a BlockingQueue and then work with the Strings.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
1

They are completely different.

Strings are immutable and comparable, therefore can be safely used as elements of a set for example.

StringBuilder is mutable and not comparable, but it can be used to manipulate its contents. You must never use mutable objects in sets or as keys of maps, and should avoid using them in many other situations.

StringBuffer is like StringBuilder, but it's also thread-safe. Since string manipulation is rarely spread across multiple threads anyway, StringBuffer is indeed less useful in practice than StringBuilder and is mainly there for historical reasons.

biziclop
  • 48,926
  • 12
  • 77
  • 104