String vs StringBuffer in Java with Example (Performance Analysis)

In this blog post, let's explore the differences between String and StringBuffer in Java with examples. We also see the performance analysis with an example.

1. Immutability 

String 

The String class in Java is immutable, meaning once a String object is created, it cannot be changed. Any modification to a String results in a new String object.

String str = "Java";
str = str + " Guides"; // Creates a new String object

StringBuffer 

On the other hand, StringBuffer is mutable, meaning that its content can be changed without creating a new object.

StringBuffer strBuffer = new StringBuffer("Java");
strBuffer.append(" Guides"); // Modifies the existing object

2. Performance

Performance differences between String and StringBuffer in Java can be significant, especially when you're dealing with a large number of string manipulations. Let's explore this with an example that demonstrates the performance of both classes.

Concatenating Strings in a Loop 

Consider a scenario where we need to concatenate a short string to an existing string repeatedly, many times.

Using String

public class StringPerformanceTest {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        
        String str = "";
        for (int i = 0; i < 100000; i++) {
            str += "a"; // Creates a new String object on each iteration
        }

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken using String: " + (endTime - startTime) + " milliseconds");
    }
}

Output:

Time taken using String: 441 milliseconds

Using StringBuffer

public class StringBufferPerformanceTest {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        
        StringBuffer strBuffer = new StringBuffer();
        for (int i = 0; i < 100000; i++) {
            strBuffer.append("a"); // Modifies the existing object
        }

        long endTime = System.currentTimeMillis();
        System.out.println("Time taken using StringBuffer: " + (endTime - startTime) + " milliseconds");
    }
}

Output:

Time taken using StringBuffer: 5 milliseconds

StringBuffer being mutable, simply modifies the existing object. This leads to much better performance.

Performance Analysis

When you run these above two examples, you will typically see a substantial difference in the execution time:

Time taken using String: 441 milliseconds
Time taken using StringBuffer: 5 milliseconds

Note: The actual times will vary depending on the system and environment.

So use String for short, simple, and infrequent string manipulations where immutability is desired. 

Use StringBuffer when dealing with complex or frequent string manipulations, especially in a loop, to gain significant performance benefits.

3. Synchronization 

String 

String Being Immutable, synchronization is not a concern with String objects. Multiple threads can access a String without risk of concurrent modification, as any changes will result in new, separate objects.

StringBuffer

All the methods in StringBuffer that change the content are synchronized. This means that only one thread at a time can execute these methods on a given StringBuffer object. If multiple threads try to modify the same StringBuffer object concurrently, synchronization ensures that only one can do so at a time, thus preventing data inconsistency.

4. Method Availability 

String and StringBuffer both provide methods for various operations, but StringBuffer has additional methods like append(), insert(), reverse(), etc., to modify the content. 

StringBuffer class methods example:
StringBuffer sb = new StringBuffer("Java");
sb.append(" Programming"); // Appends " Programming"
sb.insert(5, "Language "); // Inserts "Language " at the 5th index
sb.reverse(); // Reverses the content
System.out.println(sb.toString()); // Output: "gnimmargorP eganguaL avaJ"
The append method is used to add content to the end of the StringBuffer.
The reverse method reverses the content of the StringBuffer.
The insert method inserts content at a specified position in the StringBuffer.

String vs StringBuffer - Cheat Sheet

Conclusion 

While String and StringBuffer might seem interchangeable, their distinct characteristics make them suitable for different scenarios. 

Use String when you need a fixed, immutable sequence of characters, and you are sure that the content won't change frequently. 

Use StringBuffer when you need to perform frequent modifications to the text content, especially in a multithreaded environment. 

Understanding these differences will help you choose the right class for your specific use case, balancing performance, safety, and functionality.

Comments