In Java, a String is a sequence of characters. Strings are widely used in Java programming for storing and manipulating text. In Java, String is a built-in class and is part of the java.lang package. Unlike other objects in Java, Strings are immutable, meaning once a String is created, it cannot be modified.
String Declaration and Initialization :
In Java, you can declare and initialize a String in several ways:
- Using String literal :
String str1 = “Hello, World!”;
Here, str1 refers to a string object that contains the characters “Hello, World!”.
- Using the new keyword :
String str2 = new String(“Hello, Java!”);
This creates a new String object explicitly using the new keyword.
Immutability of Strings :
Strings in Java are immutable, meaning once a String is created, it cannot be changed. When you try to modify a String, Java creates a new String object instead of modifying the existing one. This is why string concatenation in Java may lead to performance issues in some cases (for example, in loops).
String str = “Java”;
str = str + ” Programming”; // This creates a new String object
Why Use Strings in Java?
- Immutability: String objects are immutable, meaning once a String object is created, its content cannot be changed. Any modification of a String results in the creation of a new String object. This is particularly useful when you want to ensure that the value of a string is constant throughout its lifecycle, such as in scenarios where strings represent constant data (e.g., filenames, error messages, configuration keys).
- Thread-Safety: Since String objects are immutable, they are inherently thread-safe. Multiple threads can access a String without the risk of one thread modifying it and causing inconsistency. This makes String a good choice when you want safe, shared access to a string in a multi-threaded environment.
- Simplicity and Readability: String is often the simplest and most natural choice when working with string data in Java. It has a rich set of methods for common operations (like substring, indexOf, etc.) and is used extensively in Java code.
Example:
String str = “Hello, World!”;
Here, str is immutable, and you cannot change its content directly. If you attempt to change it (e.g., by appending something), a new String object is created.
String Constructors in java :
In Java, the String class provides several constructors to create string objects. Here’s a simple explanation of each constructor:
CONSTRUCTOR | DESCRIPTION | EXAMPLE |
String(String str) | This constructor creates a new string from an existing string. It’s like copying the content of one string to make a new one. | String str = new String(“Hello”); |
String() | This constructor creates an empty string. It’s like starting with nothing, an empty space. | String str = new String(); |
String(char[] charArray) | This constructor creates a string from an array of characters. It’s like taking a group of characters (like [‘H’, ‘e’, ‘l’, ‘l’, ‘o’]) and turning them into a single string. | char[] chars = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’}; String str = new String(chars); |
String(byte[] byteArray) | This constructor creates a string from an array of bytes. Each byte is interpreted as a character, often based on a specific character encoding. | byte[] bytes = {72, 101, 108, 108, 111}; String str = new String(bytes); |
String(char[] charArray, int offset, int count) | This constructor creates a string from a section of a character array, starting from a specific position (offset) and using a certain number of characters (count). | char[] chars = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’}; String str = new String(chars, 1, 3); // Creates “ell” |
String(byte[] byteArray, int offset, int length) | This constructor creates a string from a section of a byte array, just like the one above but with specific starting position (offset) and length. | byte[] bytes = {72, 101, 108, 108, 111}; String str = new String(bytes, 0, 3); // Creates “Hel” |
String(StringBuffer buffer) | This constructor creates a string from a StringBuffer object. It’s like converting a buffer of characters into a final string. | StringBuffer buffer = new StringBuffer(“Hello”); String str = new String(buffer); |
String(StringBuilder builder) | This constructor creates a string from a StringBuilder object. It works similarly to the StringBuffer constructor. | StringBuilder builder = new StringBuilder(“Hello”); String str = new String(builder); |
String Methods :
Java’s String class provides a wide range of methods to manipulate strings. Below are some of the most commonly used methods.
String Method | Description | Example |
equals(Object obj) | Compares the string with the specified object for equality. | “abc”.equals(“abc”); // returns true |
equalsIgnoreCase(String anotherString) | Compares two strings, ignoring case differences. | “abc”.equalsIgnoreCase(“ABC”); // returns true |
compareTo(String anotherString) | Compares two strings lexicographically (dictionary order). | “apple”.compareTo(“banana”); // returns negative value |
compareToIgnoreCase(String anotherString) | Compares two strings lexicographically, ignoring case differences. | “apple”.compareToIgnoreCase(“APPLE”); // returns 0 |
charAt(int index) | Returns the character at the specified index. | “hello”.charAt(1); // returns ‘e’ |
concat(String str) | Concatenates the specified string to the end of the current string. | “hello”.concat(” world”); // returns “hello world” |
contains(CharSequence sequence) | Checks if the string contains the specified sequence of characters. | “hello”.contains(“ell”); // returns true |
substring(int beginIndex) | Returns a substring starting from the specified index. | “hello”.substring(2); // returns “llo” |
substring(int beginIndex, int endIndex) | Returns a substring from the specified start index to the end index (exclusive). | “hello”.substring(1, 4); // returns “ell” |
replace(char oldChar, char newChar) | Replaces all occurrences of the specified character with the new character. | “hello”.replace(‘l’, ‘x’); // returns “hexxo” |
replaceAll(String regex, String replacement) | Replaces all substrings that match the given regular expression with the specified replacement. | “hello123”.replaceAll(“\\d”, “#”); // returns “hello###” |
replaceFirst(String regex, String replacement) | Replaces the first substring that matches the regular expression with the specified replacement. | “hello123”.replaceFirst(“\\d”, “#”); // returns “hello#23” |
toLowerCase() | Converts the string to lowercase. | “HELLO”.toLowerCase(); // returns “hello” |
toUpperCase() | Converts the string to uppercase. | “hello”.toUpperCase(); // returns “HELLO” |
length() | Returns the number of characters in the String. | String str = “Hello, World!” int len = str.length(); // Returns 13 |
trim() | Removes leading and trailing whitespace. | ” hello “.trim(); // returns “hello” |
stripLeading() | Removes leading whitespace. | ” hello”.stripLeading(); // returns “hello” |
stripTrailing() | Removes trailing whitespace. | “hello “.stripTrailing(); // returns “hello” |
concat(String str) | Concatenates the specified string to the current string. | “hello”.concat(” world”); // returns “hello world” |
indexOf(int ch) | Returns the index of the first occurrence of the specified character. | “hello”.indexOf(‘e’); // returns 1 |
indexOf(String str) | Returns the index of the first occurrence of the specified substring. | “hello”.indexOf(“ll”); // returns 2 |
lastIndexOf(int ch) | Returns the index of the last occurrence of the specified character. | “hello”.lastIndexOf(‘l’); // returns 3 |
lastIndexOf(String str) | Returns the index of the last occurrence of the specified character. | “hello”.lastIndexOf(“l”); // returns 3 |
startsWith(String prefix) | Checks if the string starts with the specified prefix. | “hello”.startsWith(“he”); // returns true |
endsWith(String suffix) | Checks if the string ends with the specified suffix. | “hello”.endsWith(“lo”); // returns true |
toCharArray() | Converts the string to a new character array. | “hello”.toCharArray(); // returns [‘h’, ‘e’, ‘l’, ‘l’, ‘o’] |
valueOf(Object obj) | Returns the string representation of the specified object. | String.valueOf(123); // returns “123” |
format(String format, Object… args) | Returns a formatted string using the specified format and arguments. | String.format(“Hello, %s!”, “John”); // returns “Hello, John!” |
join(CharSequence delimiter, CharSequence… elements) | Joins the elements of the array into a single string, separated by the given delimiter. | String.join(“, “, “apple”, “banana”, “cherry”); // returns “apple, banana, cherry” |
repeat(int count) | Returns a new string that repeats the original string a specified number of times. | “abc”.repeat(3); // returns “abcabcabc” |
Example :
public class StringMethodsExample { public static void main(String[] args) { // Initial string String str = “Hello World”; // 1. length() – Returns the length of the string System.out.println(“Length: ” + str.length()); // Output: 11 // 2. charAt() – Returns the character at the specified index System.out.println(“Character at index 1: ” + str.charAt(1)); // Output: e // 3. equals() – Compares the string with another string (case-sensitive) System.out.println(“Equals ‘Hello World’: ” + str.equals(“Hello World”)); // Output: true // 4. equalsIgnoreCase() – Compares the string with another string (case-insensitive) System.out.println(“EqualsIgnoreCase ‘hello world’: ” + str.equalsIgnoreCase(“hello world”)); // Output: true // 5. compareTo() – Compares two strings lexicographically System.out.println(“CompareTo ‘Hello World’: ” + str.compareTo(“Hello World”)); // Output: 0 // 6. compareToIgnoreCase() – Compares two strings lexicographically (ignoring case) System.out.println(“CompareToIgnoreCase ‘hello world’: ” + str.compareToIgnoreCase(“hello world”)); // Output: 0 // 7. contains() – Checks if the string contains a sequence of characters System.out.println(“Contains ‘World’: ” + str.contains(“World”)); // Output: true // 8. startsWith() – Checks if the string starts with the specified prefix System.out.println(“Starts with ‘Hello’: ” + str.startsWith(“Hello”)); // Output: true // 9. endsWith() – Checks if the string ends with the specified suffix System.out.println(“Ends with ‘World’: ” + str.endsWith(“World”)); // Output: true // 10. indexOf() – Returns the index of the first occurrence of the specified character System.out.println(“Index of ‘o’: ” + str.indexOf(‘o’)); // Output: 4 // 11. lastIndexOf() – Returns the index of the last occurrence of the specified character System.out.println(“Last index of ‘o’: ” + str.lastIndexOf(‘o’)); // Output: 7 // 12. substring() – Returns a substring starting from the specified index System.out.println(“Substring from index 6: ” + str.substring(6)); // Output: World // 13. substring() – Returns a substring between two indices System.out.println(“Substring from index 0 to 5: ” + str.substring(0, 5)); // Output: Hello // 14. toLowerCase() – Converts all characters to lowercase System.out.println(“Lowercase: ” + str.toLowerCase()); // Output: hello world // 15. toUpperCase() – Converts all characters to uppercase System.out.println(“Uppercase: ” + str.toUpperCase()); // Output: HELLO WORLD // 16. trim() – Removes leading and trailing spaces String strWithSpaces = ” Hello World “; System.out.println(“Trimmed: ‘” + strWithSpaces.trim() + “‘”); // Output: ‘Hello World’ // 17. replace() – Replaces all occurrences of a specified character System.out.println(“Replace ‘o’ with ‘0’: ” + str.replace(‘o’, ‘0’)); // Output: Hell0 W0rld // 18. replaceAll() – Replaces substrings matching a regular expression System.out.println(“Replace all ‘o’ with ‘0’ using regex: ” + str.replaceAll(“o”, “0”)); // Output: Hell0 W0rld // 19. split() – Splits the string based on the specified delimiter String[] words = str.split(” “); System.out.println(“Split by space: “); for (String word : words) { System.out.println(word); // Output: Hello, World } // 20. valueOf() – Converts a given value (e.g., integer) into a string int number = 123; System.out.println(“Value of 123 as String: ” + String.valueOf(number)); // Output: 123 } } |
Output :
Length: 11 Character at index 1: e Equals ‘Hello World’: true EqualsIgnoreCase ‘hello world’: true CompareTo ‘Hello World’: 0 CompareToIgnoreCase ‘hello world’: 0 Contains ‘World’: true Starts with ‘Hello’: true Ends with ‘World’: true Index of ‘o’: 4 Last index of ‘o’: 7 Substring from index 6: World Substring from index 0 to 5: Hello Lowercase: hello world Uppercase: HELLO WORLD Trimmed: ‘Hello World’ Replace ‘o’ with ‘0’: Hell0 W0rld Replace all ‘o’ with ‘0’ using regex: Hell0 W0rld Split by space: Hello World Value of 123 as String: 123 |
StringBuilder and StringBuffer :
Although String objects are immutable, if you need to modify a string repeatedly (such as in loops), it’s better to use StringBuilder or StringBuffer.
- StringBuilder is faster but not thread-safe.
- StringBuffer is thread-safe but slower than StringBuilder.
StringBuffer in Java :
- StringBuffer is a class that allows the modification of strings without creating a new string object each time.
- It provides methods for appending, inserting, or deleting characters from a string.
- StringBuffer objects are mutable, meaning that once a StringBuffer object is created, it can be modified without creating a new instance.
- It is particularly useful when you perform frequent modifications to a string (e.g., concatenation) in a loop.
Key Characteristics of StringBuffer :
- Thread-Safe: StringBuffer is thread-safe. This means it is synchronized internally, which ensures that it can be used safely in a multi-threaded environment.
- Performance: Due to its thread-safety, StringBuffer can be slower than StringBuilder in single-threaded environments, but it ensures that concurrent modifications are handled safely.
Why Use StringBuffer in Java?
StringBuffer is used when you need to manipulate strings in a way that allows for efficient modification, especially when the string is being modified multiple times.
- Mutability: Unlike String, a StringBuffer object is mutable, meaning that it allows modification of the string content without creating new objects each time. This makes StringBuffer more efficient than String for operations like concatenation inside loops.
- Thread-Safety: StringBuffer is thread-safe because its methods are synchronized. This means that multiple threads can safely access and modify the same StringBuffer object concurrently without causing data inconsistency.
- Use Case: StringBuffer is commonly used when you need to perform many string manipulations (e.g., appending, inserting, or deleting characters) and need to do so in a multi-threaded environment where thread safety is important.
Constructors :
- StringBuffer(): Creates a new StringBuffer object with no characters.
- StringBuffer(int capacity): Creates a new StringBuffer with the specified initial capacity.
- StringBuffer(String str): Creates a new StringBuffer initialized to the specified string.
Methods in StringBuffer :
Method | Description |
append(String str) | Appends the specified string to the StringBuffer. |
append(char c) | Appends the specified character to the StringBuffer. |
insert(int offset, String str) | Inserts the specified string at the given index (offset). |
insert(int offset, char c) | Inserts the specified character at the given index (offset). |
delete(int start, int end) | Deletes the substring from the StringBuffer starting at the specified index start and ending at end (exclusive). |
deleteCharAt(int index) | Deletes the character at the specified index. |
replace(int start, int end, String str) | Replaces the characters in the StringBuffer between the start and end indices with the specified string. |
reverse() | Reverses the content of the StringBuffer. |
capacity() | Returns the current capacity of the StringBuffer. |
length() | Returns the length of the string. |
indexOf(String str) | Returns the index of the first occurrence of the specified substring. |
lastIndexOf(String str) | Returns the index of the last occurrence of the specified substring. |
indexOf(String str, int fromIndex) | Returns the index of the first occurrence of the specified substring, starting from the specified index. |
lastIndexOf(String str, int fromIndex) | Returns the index of the last occurrence of the specified substring, starting from the specified index. |
toString() | Converts the StringBuffer to a string and returns the result. |
charAt(int index) | Returns the character at the specified index. |
subSequence(int start, int end) | Returns a new CharSequence that is a subsequence of the characters from the specified start to end indices. |
Example :
public class StringBufferMethodsExample { public static void main(String[] args) { // Initialize a StringBuffer StringBuffer sb = new StringBuffer(“Hello”); // 1. append() sb.append(” World”); // “Hello World” System.out.println(“After append: ” + sb); // 2. insert() sb.insert(5, “,”); // “Hello, World” System.out.println(“After insert: ” + sb); // 3. delete() sb.delete(5, 6); // “Hello World” System.out.println(“After delete: ” + sb); // 4. deleteCharAt() sb.deleteCharAt(5); // removes the space: “HelloWorld” System.out.println(“After deleteCharAt: ” + sb); // 5. replace() sb.replace(5, 9, “o World”); // replaces “Worl” with “o World” System.out.println(“After replace: ” + sb); // 6. reverse() sb.reverse(); // reverses string System.out.println(“After reverse: ” + sb); // 7. indexOf() System.out.println(“Index of ‘o’: ” + sb.indexOf(“o”)); // 8. toString() String str = sb.toString(); System.out.println(“String: ” + str); // 9. capacity() System.out.println(“Capacity: ” + sb.capacity()); } } |
Output :
After append: Hello World After insert: Hello, World After delete: Hello World After deleteCharAt: HelloWorld After replace: Helloo Worldd After reverse: ddlroW oolleH Index of ‘o’: 6 String: ddlroW oolleH Capacity: 21 |
StringBuilder in Java :
- StringBuilder is similar to StringBuffer but is not synchronized, making it faster than StringBuffer in environments where thread safety is not a concern.
- StringBuilder is ideal for situations where you perform many string manipulations in a single-threaded environment.
Key Characteristics of StringBuilder :
- Not Thread-Safe: StringBuilder is not synchronized, meaning that it is not thread-safe. However, it is faster than StringBuffer in single-threaded applications because it does not have the overhead of synchronization.
- Performance: If thread safety is not required, StringBuilder provides better performance compared to StringBuffer.
- Mutability: Like StringBuffer, StringBuilder objects are mutable, allowing modification of their contents without creating a new string object.
Why Use StringBuilder in Java?
StringBuilder is similar to StringBuffer, but it is not thread-safe, which makes it more efficient in scenarios where thread safety is not a concern. It’s generally preferred when you are working with strings in a single-threaded environment.
- Mutability: Like StringBuffer, StringBuilder is mutable, meaning you can modify its content without creating new objects each time. This makes it more memory- and performance-efficient for string manipulations.
- Faster Than StringBuffer: StringBuilder is faster than StringBuffer because it is not synchronized. When you don’t need thread safety, StringBuilder can be a better choice due to its lower overhead.
- Use Case: StringBuilder is ideal when you need to modify strings frequently in a single-threaded application, such as in loops or when concatenating a large number of strings.
Constructors :
- StringBuilder(): Creates an empty StringBuilder with a default capacity.
- StringBuilder(int capacity): Creates a StringBuilder with the specified initial capacity.
- StringBuilder(String str): Creates a StringBuilder initialized to the contents of the specified string.
Methods in StringBuilder :
Method | Description |
length() | Returns the length (the number of characters) of the StringBuilder. |
capacity() | Returns the current capacity of the StringBuilder. |
append(String str) | Appends the specified string to the StringBuilder. |
append(char c) | Appends the specified character to the StringBuilder. |
insert(int offset, String str) | Inserts the specified string at the specified position (index). |
insert(int offset, char c) | Inserts the specified character at the specified position (index). |
delete(int start, int end) | Deletes the substring from the StringBuilder between the specified start and end indices. |
deleteCharAt(int index) | Deletes the character at the specified index. |
replace(int start, int end, String str) | Replaces the characters from the specified start index to end index with the specified string. |
reverse() | Reverses the contents of the StringBuilder. |
indexOf(String str) | Returns the index of the first occurrence of the specified substring. |
lastIndexOf(String str) | Returns the index of the last occurrence of the specified substring. |
indexOf(String str, int fromIndex) | Returns the index of the first occurrence of the specified substring, starting from the given index. |
lastIndexOf(String str, int fromIndex) | Returns the index of the last occurrence of the specified substring, starting from the given index. |
Example :
public class StringBuilderMethodsExample { public static void main(String[] args) { // Initialize StringBuilder StringBuilder sb = new StringBuilder(“Hello”); // 1. append() sb.append(” World”); System.out.println(“After append: ” + sb); // Output: Hello World // 2. insert() sb.insert(5, “,”); System.out.println(“After insert: ” + sb); // Output: Hello, World // 3. delete() sb.delete(5, 6); // Remove the comma System.out.println(“After delete: ” + sb); // Output: Hello World // 4. deleteCharAt() sb.deleteCharAt(5); // Remove space System.out.println(“After deleteCharAt: ” + sb); // Output: HelloWorld // 5. replace() sb.replace(5, 10, ” Java”); System.out.println(“After replace: ” + sb); // Output: Hello Java // 6. reverse() sb.reverse(); System.out.println(“After reverse: ” + sb); // Output: avaJ olleH // 7. indexOf() System.out.println(“Index of ‘a’: ” + sb.indexOf(“a”)); // Output: 0 // 8. toString() String str = sb.toString(); System.out.println(“String: ” + str); // Output: avaJ olleH // 9. capacity() System.out.println(“Capacity: ” + sb.capacity()); // Output: 21 } } |
Output :
After append: Hello World After insert: Hello, World After delete: Hello World After deleteCharAt: HelloWorld After replace: Hello Java After reverse: avaJ olleH Index of ‘a’: 0 String: avaJ olleH Capacity: 21 |
Comparison :
Feature | String | StringBuffer | StringBuilder |
Immutability | Immutable (cannot be changed) | Mutable (can be modified) | Mutable (can be modified) |
Thread Safety | Thread-safe (immutable) | Thread-safe (synchronized methods) | Not thread-safe |
Performance | Less efficient (due to immutability) | Slower (due to synchronization) | Faster (no synchronization overhead) |
Use Case | For constant values and safe concurrent access | When frequent modifications in a multi-threaded environment are needed | For frequent modifications in a single-threaded environment |
Memory Efficiency | Less efficient for frequent modifications | More efficient than String for frequent modifications | More efficient than StringBuffer for frequent modifications in single-threaded environments |
Conclusion :
In conclusion, String is best for static text, while StringBuffer and StringBuilder are suited for dynamic string modifications. Use StringBuffer when thread-safety is needed, and StringBuilder for better performance in single-threaded environments. Choosing the right class helps optimize performance and memory usage in Java applications.