When working with JSON data in real-world applications, it is very common to deal with collections, especially lists of objects. Jackson provides easy and powerful mechanisms to handle JSON arrays and convert them into Java collections, such as List<User>.
1. What Is Collection Handling?
Collection handling refers to the process of deserializing a JSON array into a Java collection (usually a List, Set, or Map) of objects, and serializing a Java collection back into a JSON array.
2. Why Is This Important?
API responses often return lists of items (e.g., list of users, orders, products).
Data persistence can involve storing or reading multiple records in a structured JSON array format.
public class User {
private String name;
private int age;
public User() { }
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and Setters
}
4.1. Deserialize JSON Array into List<User>
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.List;
public class JacksonCollectionDeserializationExample {
public static void main(String[] args) {
try {
ObjectMapper objectMapper = new ObjectMapper();
// Read JSON array from file
File jsonFile = new File("users.json");
// Deserialize JSON array into List<User>
List < User > users = objectMapper.readValue(jsonFile, new TypeReference < List < User >> () {});
// Iterate over users
for (User user: users) {
System.out.println("Name: " + user.getName() + ", Age: " + user.getAge());
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
➤ Explanation of Key Concepts:
new TypeReference<List<User>>() {} is necessary because of Java’s type erasure: It tells Jackson the full generic type to deserialize into, since List<User> cannot be determined at runtime without help.
The JSON file (users.json) contains an array of user objects.
would return a List<Map<String, Object>> instead of List<User>.
By using:
new TypeReference<List<User>>() {}
Jackson understands the correct mapping.
6. When to Use Collection Handling
Scenario
Use Case
API returns a list of entities
Deserialize JSON array into List<User>
Bulk data persistence
Serialize List<User> into JSON array in a file
Data transformation
Map JSON array to Java collection, then manipulate data
✅ Conclusion
Handling collections is a critical aspect of real-world JSON processing. Jackson’s combination of TypeReference, ObjectMapper.readValue(), and writeValue() makes it effortless to convert JSON arrays into Java collections and back. This ensures efficient, type-safe handling of structured batch data from APIs, configuration files, or persistent storage.
Jackson provides a set of powerful annotations that help customize how Java objects are serialized into JSON and deserialized back into Java objects. These annotations allow fine-grained control over the mapping behavior without modifying the core logic of your application.
Common Jackson Annotations
✅ @JsonProperty
Purpose: Maps a Java field or getter/setter to a specific JSON property name during serialization and deserialization.
Useful when the JSON property name does not match the Java field name.
Example:
import com.fasterxml.jackson.annotation.JsonProperty;
public class Employee {
@JsonProperty("full_name")
private String name;
private int age;
public Employee() { }
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and Setters
}
👉 In this case, the JSON property will be "full_name" instead of "name".
Serialization Example:
ObjectMapper objectMapper = new ObjectMapper();
Employee emp = new Employee("Ashish Kumar", 30);
String jsonString = objectMapper.writeValueAsString(emp);
System.out.println(jsonString);
Output:
{"full_name":"Ashish Kumar","age":30}
✅ @JsonIgnore
Purpose: Prevents a specific field from being serialized (Java to JSON) or deserialized (JSON to Java).
Useful for sensitive data (like passwords) or unnecessary properties.
Example:
import com.fasterxml.jackson.annotation.JsonIgnore;
public class Employee {
private String name;
private int age;
@JsonIgnore
private String password;
public Employee() { }
public Employee(String name, int age, String password) {
this.name = name;
this.age = age;
this.password = password;
}
// Getters and Setters
}
Serialization Example:
ObjectMapper objectMapper = new ObjectMapper();
Employee emp = new Employee("Ashish Kumar", 30, "secure123");
String jsonString = objectMapper.writeValueAsString(emp);
System.out.println(jsonString);
👉 The password field will be excluded from the JSON output and will not be read during deserialization.
Output:
{"name":"Ashish Kumar","age":30}
✅ @JsonInclude
Purpose: Controls the inclusion of properties during serialization based on certain conditions (e.g., exclude null values).
Example usage: Exclude null fields to reduce output size.
Example:
import com.fasterxml.jackson.annotation.JsonInclude;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Employee {
private String name;
private Integer age;
private String department;
public Employee() { }
public Employee(String name, Integer age, String department) {
this.name = name;
this.age = age;
this.department = department;
}
// Getters and Setters
}
Serialization Example:
ObjectMapper objectMapper = new ObjectMapper();
Employee emp = new Employee("Ashish Kumar", 30, null);
String jsonString = objectMapper.writeValueAsString(emp);
System.out.println(jsonString);
👉 Fields with null values (like department if not set) will be excluded from the serialized JSON.
The @JsonIgnoreProperties annotation is used to ignore multiple unknown properties during deserialization.
By default, if the incoming JSON contains fields that do not match any properties in the target Java class, Jackson throws an exception (UnrecognizedPropertyException).
Adding @JsonIgnoreProperties(ignoreUnknown = true) prevents this exception by simply ignoring any unknown fields.
➤ Why Is It Useful?
Useful when the JSON comes from an external source (like a third-party API) that may include additional fields your Java class does not care about.
Avoids tightly coupling your Java model to every field in the JSON.
Example:
JSON Input:
{
"name": "Ashish Kumar",
"age": 30,
"extra": "this field is not mapped in Java class"
}
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public class Employee {
private String name;
private int age;
// Getters and Setters
}
Behavior:
The extra field will be ignored during deserialization.
No exception will be thrown, and only name and age will be mapped.
✅ @JsonCreator and @JsonProperty Combination
These annotations are used when deserializing into immutable objects or when the target class does not have a default (no-argument) constructor.
@JsonCreator: Marks the constructor to be used for deserialization.
@JsonProperty: Specifies how the constructor arguments map to JSON properties.
➤ Why Is It Useful?
Ensures proper deserialization when using final fields or classes designed to be immutable.
Promotes safe object construction without relying on setters.
JSON Input:
{
"name": "Ashish Kumar",
"age": 30
}
Java Class:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Employee {
private final String name;
private final int age;
@JsonCreator
public Employee(@JsonProperty("name") String name, @JsonProperty("age") int age) {
this.name = name;
this.age = age;
}
// Getters
public String getName() { return name; }
public int getAge() { return age; }
}
Behavior:
Jackson uses the annotated constructor to instantiate the object.
No need for a default constructor or setters.
Allows fully immutable objects while still supporting deserialization.
✅ Conclusion
@JsonProperty → Maps a Java field to a specific JSON property name.
@JsonIgnore → Prevents a field from being serialized or deserialized.
@JsonInclude → Controls inclusion of properties during serialization (e.g., omit nulls).
These annotations remain stable and correct in the latest Jackson versions (e.g., 2.15.x) and Java versions (e.g., Java 17 or later).
@JsonIgnoreProperties(ignoreUnknown = true) helps prevent errors caused by unexpected fields in JSON.
@JsonCreator with @JsonProperty enables deserialization into immutable objects by mapping constructor arguments directly from JSON properties.
Jackson is a widely used Java library for processing JSON data. It provides easy-to-use APIs for serializing Java objects to JSON and deserializing JSON into Java objects. Jackson is popular due to its high performance, flexible configuration, and powerful data-binding features.
What is Jackson?
Jackson is a high-performance JSON processor for Java. It helps convert Java objects to JSON and vice versa. The core class is ObjectMapper, and it also provides useful annotations for customization.
readTree(String json) → Parse JSON into a tree of JsonNode.
2. Serialization (Marshalling)
What is Serialization?
Serialization is the process of converting a Java object into a format (in this case, JSON) that can be easily stored or transmitted, and later reconstructed back into the original object. In the context of Jackson, serialization is also known as marshalling.
When working with APIs, databases, or file storage, JSON is commonly used to represent structured data in a lightweight and human-readable format. Jackson’s ObjectMapper makes this conversion simple and efficient.
2.1 Serialization Java Object to JSON
✔️ Example User.java Class
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
// Getters and Setters
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
✔️ Serialization Example
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonSerializationExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();//Create an instance of ObjectMapper
User user = new User("Ashish Kumar", 30);
String jsonString = objectMapper.writeValueAsString(user);//Serialize the Object to JSON String
System.out.println("Serialized JSON: " + jsonString);
}
}
➔ Output:
{"name":"Ashish Kumar","age":30}
2.2 Writing JSON to a File
⚡ Instead of working only with strings, Jackson allows you to directly write JSON into files using:
✔️ Example
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
public class JacksonWriteToFileExample {
public static void main(String[] args) {
try {
// Create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
// Create a User object
User user = new User("Ashish Kumar", 30);
// Write the User object as JSON to the file "user.json"
objectMapper.writeValue(new File("user.json"), user);
System.out.println("JSON file has been written successfully.");
} catch (Exception e) {
e.printStackTrace();
}
}
}
➔Output : Resulting File Content (user.json):
{"name":"Ashish Kumar","age":30}
👉This approach is helpful when persisting data or creating configuration files.
✅ Why Is This Useful?
Data Transmission: Serialized JSON is easy to send over HTTP in REST APIs.
Data Storage: Persist objects in a JSON file for later retrieval.
Logging and Debugging: Easily log object states in a readable format.
Configuration Files: Store application settings in JSON.
3. Deserialization (Unmarshalling)
What is Deserialization?
Deserialization is the process of converting JSON data into a Java object. In the context of Jackson, this process is often called unmarshalling. It allows us to take a structured JSON string (or file) and transform it into a corresponding Java object so that we can easily work with the data in a type-safe manner.
✅ Why Is Deserialization Important?
Reading API Responses: When calling REST APIs, the response is often in JSON format. To work with the data in Java, we deserialize it into objects.
Reading Configuration Files: JSON configuration files are commonly used for application settings.
Data Persistence: Deserialize stored JSON files back into Java objects for processing or display.
✅ How Does Jackson Perform Deserialization?
Once Jackson is imported and the ObjectMapper is available, we use it to convert JSON strings or files into Java objects.
3.1 Deserialization JSON String to Java Object
✔️ Example JSON String
{"name":"Simone","age":28}
Deserialization Example
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonDeserializationExample {
public static void main(String[] args) {
try {
ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{\"name\":\"Bhasker\",\"age\":28}";
User user = objectMapper.readValue(jsonString, User.class);
System.out.println("Name: " + user.getName());
System.out.println("Age: " + user.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
Name: Bhasker
Age: 28
👉This shows how the JSON string is parsed and converted into a User object.
3.2 Deserializing from a JSON File to Java Object
✔️ Example JSON File (user.json):
{
"name": "Bhasker",
"age": 28
}
✔️ Example Java Code:
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
public class JacksonReadFileExample {
public static void main(String[] args) {
try {
ObjectMapper objectMapper = new ObjectMapper();
File jsonFile = new File("user.json");
User user = objectMapper.readValue(jsonFile, User.class);
System.out.println("Name: " + user.getName());
System.out.println("Age: " + user.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
}
👉This approach is helpful when working with large or persistent JSON data stored in files.
Output :
Name: Bhasker
Age: 28
✅ How Does Jackson Know How to Map JSON to Java Object?
Jackson relies on:
Default Constructor: The target class must have a no-argument constructor (can be implicit).
Getters and Setters: Jackson uses public setters to set values during deserialization.
Field Matching: JSON property names must match Java field names, unless annotations (like @JsonProperty) are used to map them explicitly.
4. Jackson Annotations
Jackson provides useful annotations to control serialization and deserialization.
Common Jackson Annotations
@JsonProperty → Maps a Java field to a specific JSON property name
@JsonIgnore → Prevents a specific field from being serialized or deserialized.
@JsonInclude → Controls inclusion of properties during serialization (e.g., omit nulls).
@JsonIgnoreProperties → Prevents multiple unknown fields from causing exceptions during deserialization.
@JsonCreator → Useful when deserializing immutable objects with final fields and no default constructor.
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTreeExample {
public static void main(String[] args) throws Exception {
String json = "{\"name\":\"Ashish\",\"age\":30}";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(json);
System.out.println("Name: " + node.get("name").asText());
System.out.println("Age: " + node.get("age").asInt());
}
}
Output :
Name: Ashish
Age: 30
6. Handling Collections
✅ What Is Collection Handling?
Collection handling refers to the process of deserializing a JSON array into a Java collection (usually a List, Set, or Map) of objects, and serializing a Java collection back into a JSON array.
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class JacksonListExample {
public static void main(String[] args) throws Exception {
String json = "[{\"name\":\"Bhasker\",\"age\":28}, {\"name\":\"Ashish\",\"age\":30}]";
ObjectMapper mapper = new ObjectMapper();
List < User > users = mapper.readValue(json, new TypeReference < List < User >> () {});
for (User u: users) {
System.out.println(u.getName() + " - " + u.getAge());
}
}
}
Output :
Bhasker - 28
Ashish - 30
7. Reading List of Objects from JSON File
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.File;
import java.util.List;
public class JacksonReadListFromFileExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
File jsonFile = new File("users.json");
List<User> users = objectMapper.readValue(jsonFile, new TypeReference<List<User>>() {});
for (User user : users) {
System.out.println(user.getName() + " - " + user.getAge());
}
}
}
8. Pretty Printing JSON
When working with JSON data, especially for debugging, configuration files, or manual inspection, a compact JSON string without any formatting can be hard to read. By default, Jackson produces a compact JSON output like this:
{"name":"Ashish Kumar","age":30}
This is fine for machine processing but not ideal for humans. To make the JSON output more readable, we use Pretty Printing to add line breaks, indentation, and proper spacing.
✔️ Example
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
public class JacksonPrettyPrintExample {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
User user = new User("Ashish Kumar", 30);
String prettyJson = objectMapper.writeValueAsString(user);
System.out.println(prettyJson);
}
}
Output:
{
"name" : "Ashish Kumar",
"age" : 30
}
9. Common Exceptions to Handle
JsonProcessingException
UnrecognizedPropertyException
MismatchedInputException
Summary of ObjectMapper Usage
Operation
Method Example
Serialize Object to String
writeValueAsString(obj)
Serialize Object to File
writeValue(new File("output.json"), obj)
Deserialize String to Object
readValue(jsonString, User.class)
Deserialize File to Object
readValue(new File("user.json"), User.class)
Read Tree Model
readTree(jsonString)
Deserialize Array from File
readValue(new File("users.json"), new TypeReference<List<User>>(){})
Pretty Print
Enable SerializationFeature.INDENT_OUTPUT
🎯Conclusion
Jackson is a powerful and flexible library that makes working with JSON in Java effortless. By mastering serialization, deserialization, annotations, tree model, file handling, collections, and pretty printing, you can efficiently handle JSON data in any Java project.
When working with text data in Java, there are three commonly used classes to handle strings:
String
StringBuffer
StringBuilder
Each of these serves a different purpose and has its own advantages and limitations. Understanding when and how to use them is key for writing efficient Java programs.
✅ 1. String
Immutable Object: Once a String object is created, its value cannot be changed.
Every modification creates a new String object in memory.
Useful when the string content doesn’t change often.
🔧 Example:
public class StringExample {
public static void main(String[] args) {
String text = "Java Knowledge Base";
System.out.println("Original String: " + text);
// Concatenation creates a new String object
text = text + " - Learn Java Effectively";
System.out.println("Modified String: " + text);
}
}
✅ Output:
Original String: Java Knowledge Base
Modified String: Java Knowledge Base - Learn Java Effectively
⚡ Key Point: Inefficient for many modifications due to creation of new objects and higher memory consumption.
✅ 2. StringBuffer
Mutable Class: Allows modification of the string content without creating new objects.
Thread-Safe: All methods are synchronized.
Suitable when thread safety is required.
🔧 Example:
public class StringBufferExample {
public static void main(String[] args) {
StringBuffer textBuffer = new StringBuffer("Java Knowledge Base");
System.out.println("Original StringBuffer: " + textBuffer);
// Append text
textBuffer.append(" - Learn Java Effectively");
System.out.println("Modified StringBuffer: " + textBuffer);
// Insert text
textBuffer.insert(5, " Awesome");
System.out.println("After Insert: " + textBuffer);
}
}
✅ Output:
Original StringBuffer: Java Knowledge Base
Modified StringBuffer: Java Knowledge Base - Learn Java Effectively
After Insert: Java Awesome Knowledge Base - Learn Java Effectively
⚡ Key Point: Suitable for multi-threaded environments but slightly slower than StringBuilder.
✅ 3. StringBuilder
Mutable Class: Like StringBuffer, but not synchronized (not thread-safe).
Faster than StringBuffer due to the lack of synchronization.
Recommended when working in a single-threaded context.
🔧 Example:
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder textBuilder = new StringBuilder("Java Knowledge Base");
System.out.println("Original StringBuilder: " + textBuilder);
// Append text
textBuilder.append(" - Learn Java Effectively");
System.out.println("Modified StringBuilder: " + textBuilder);
// Insert text
textBuilder.insert(5, " Awesome");
System.out.println("After Insert: " + textBuilder);
}
}
✅ Output:
Original StringBuilder: Java Knowledge Base
Modified StringBuilder: Java Knowledge Base - Learn Java Effectively
After Insert: Java Awesome Knowledge Base - Learn Java Effectively
⚡ Key Point: Best choice when working in a single-threaded environment and performance is critical.
⚔️ Comparison Table
Feature
String
StringBuffer
StringBuilder
Mutability
Immutable
Mutable
Mutable
Thread Safety
Not applicable
Thread-safe (synchronized)
Not thread-safe
Performance
Slow for modifications
Slower than StringBuilder
Fast (better performance)
Use Case
Static text or rarely changed
Multi-threaded context
Single-threaded context
Memory Usage
High (creates new objects)
Moderate
Moderate
✅ Conclusion
Use String when the string content does not change.
Use StringBuffer when you need thread safety.
Use StringBuilder for efficient single-threaded string manipulation
In Java, handling strings efficiently is crucial, especially when frequent modifications are involved. The StringBuffer class is a powerful alternative to String for such scenarios. Unlike String, which is immutable, StringBuffer allows modification of string content without creating a new object every time, making it ideal for performance-critical applications.
What is StringBuffer in Java?
StringBuffer is a thread-safe, mutable sequence of characters provided by Java in the java.lang package. It allows modification of strings (append, insert, delete, reverse, etc.) without creating new objects, which improves memory efficiency and performance.
Key Characteristics
Mutable: The content can be changed.
Thread-safe: Methods are synchronized, making it suitable for multi-threaded environments.
Efficient for frequent modifications.
String vs StringBuffer vs StringBuilder
Feature
String
StringBuffer
StringBuilder
Mutability
Immutable
Mutable
Mutable
Thread Safety
Not Thread-safe
Thread-safe
Not Thread-safe
Performance
Less efficient in loops
Slower than StringBuilder but thread-safe
Fast and efficient for single-threaded use cases
Creating a StringBuffer Object
StringBuffer sb1 = new StringBuffer(); // Creates an empty buffer with default capacity (16)
StringBuffer sb2 = new StringBuffer("Hello"); // Creates buffer initialized with "Hello"
StringBuffer sb3 = new StringBuffer(50); // Creates empty buffer with specified capacity
Common StringBuffer Methods and Examples
1. append()
Appends the specified string to this buffer.
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World
2. insert()
Inserts the specified string at the specified index.
StringBuffer sb = new StringBuffer("Hello World");
sb.insert(5, ",");
System.out.println(sb); // Output: Hello, World
3. replace()
Replaces characters from start index to end index with a new string.
StringBuffer sb = new StringBuffer("Hello");
sb.reverse();
System.out.println(sb); // Output: olleH
6. capacity() and ensureCapacity()
capacity(): Returns current capacity.
ensureCapacity(int minCapacity): Increases capacity if needed.
StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // Default is 16
sb.ensureCapacity(50);
System.out.println(sb.capacity()); // At least 50
Scenario Examples
Scenario 1: Building a Large String Efficiently
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(", ");
}
System.out.println(sb.substring(0, 50) + "...");
Why StringBuffer? Using String would create a new object on each iteration, leading to performance overhead.
Scenario 2: Multi-threaded Environment
public class StringBufferExample {
private static StringBuffer buffer = new StringBuffer();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> buffer.append("A"));
Thread t2 = new Thread(() -> buffer.append("B"));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(buffer.toString()); // Output: AB or BA (depends on thread scheduling)
}
}
When to Use StringBuffer vs StringBuilder
Use StringBuffer when working in multi-threaded environments where thread safety is needed.
Use StringBuilder when thread safety is not required for better performance.
Important Points to Remember
StringBuffer is synchronized, making it thread-safe.
Always prefer StringBuilder for non-concurrent scenarios due to better performance.
StringBuffer’s capacity grows automatically but can be managed using ensureCapacity().
Conclusion
StringBuffer is a powerful tool in Java for mutable and thread-safe string manipulation. Understanding its methods and appropriate use cases is key to writing efficient Java applications.
In Java, handling strings efficiently is crucial, especially when frequent modifications are involved. The StringBuffer class is a powerful alternative to String for such scenarios. Unlike String, which is immutable, StringBuffer allows modification of string content without creating a new object every time, making it ideal for performance-critical applications.
What is StringBuffer in Java?
StringBuffer is a thread-safe, mutable sequence of characters provided by Java in the java.lang package. It allows modification of strings (append, insert, delete, reverse, etc.) without creating new objects, which improves memory efficiency and performance.
Key Characteristics
Mutable: The content can be changed.
Thread-safe: Methods are synchronized, making it suitable for multi-threaded environments.
Efficient for frequent modifications.
String vs StringBuffer vs StringBuilder
Feature
String
StringBuffer
StringBuilder
Mutability
Immutable
Mutable
Mutable
Thread Safety
Not Thread-safe
Thread-safe
Not Thread-safe
Performance
Less efficient in loops
Slower than StringBuilder but thread-safe
Fast and efficient for single-threaded use cases
Creating a StringBuffer Object
StringBuffer sb1 = new StringBuffer(); // Creates an empty buffer with default capacity (16)
StringBuffer sb2 = new StringBuffer("Hello"); // Creates buffer initialized with "Hello"
StringBuffer sb3 = new StringBuffer(50); // Creates empty buffer with specified capacity
Common StringBuffer Methods and Examples
1. append()
Appends the specified string to this buffer.
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World
2. insert()
Inserts the specified string at the specified index.
StringBuffer sb = new StringBuffer("Hello World");
sb.insert(5, ",");
System.out.println(sb); // Output: Hello, World
3. replace()
Replaces characters from start index to end index with a new string.
StringBuffer sb = new StringBuffer("Hello");
sb.reverse();
System.out.println(sb); // Output: olleH
6. capacity() and ensureCapacity()
capacity(): Returns current capacity.
ensureCapacity(int minCapacity): Increases capacity if needed.
StringBuffer sb = new StringBuffer();
System.out.println(sb.capacity()); // Default is 16
sb.ensureCapacity(50);
System.out.println(sb.capacity()); // At least 50
Scenario Examples
Scenario 1: Building a Large String Efficiently
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 1000; i++) {
sb.append(i).append(", ");
}
System.out.println(sb.substring(0, 50) + "...");
Why StringBuffer? Using String would create a new object on each iteration, leading to performance overhead.
Scenario 2: Multi-threaded Environment
public class StringBufferExample {
private static StringBuffer buffer = new StringBuffer();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> buffer.append("A"));
Thread t2 = new Thread(() -> buffer.append("B"));
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(buffer.toString()); // Output: AB or BA (depends on thread scheduling)
}
}
When to Use StringBuffer vs StringBuilder
Use StringBuffer when working in multi-threaded environments where thread safety is needed.
Use StringBuilder when thread safety is not required for better performance.
Important Points to Remember
StringBuffer is synchronized, making it thread-safe.
Always prefer StringBuilder for non-concurrent scenarios due to better performance.
StringBuffer’s capacity grows automatically but can be managed using ensureCapacity().
Conclusion
StringBuffer is a powerful tool in Java for mutable and thread-safe string manipulation. Understanding its methods and appropriate use cases is key to writing efficient Java applications.