4.4 String Manipulation
In Java, a String is an object that represents a sequence of characters. Unlike arrays, Strings are objects and come with built-in methods for various operations.
Key Characteristics
- Immutable: Once created, cannot be modified
- Sequence of characters: Supports Unicode characters
- Object type: Not a primitive data type
- Special support: String literals and + operator overloading
String Memory Management
java
String str1 = "Hello"; // String literal (stored in string pool)
String str2 = new String("Hello"); // String object (stored in heap)
String Creation and Initialization
1. Using String Literals
java
String greeting = "Hello, World!";
String empty = ""; // Empty string
String name = "John Doe";
2. Using new
Keyword
java
String str1 = new String(); // Empty string
String str2 = new String("Hello"); // From string literal
String str3 = new String(new char[]{'H', 'i'}); // From char array
3. From Character Arrays
java
char[] charArray = {'J', 'a', 'v', 'a'};
String fromCharArray = new String(charArray);
String fromSubArray = new String(charArray, 1, 2); // "av" (offset 1, length 2)
4. From StringBuffer and StringBuilder
java
StringBuffer buffer = new StringBuffer("Hello");
String fromBuffer = new String(buffer);
StringBuilder builder = new StringBuilder("World");
String fromBuilder = new String(builder);
5. Special Cases
java
// Multi-line strings (Java 13+)
String html = """
<html>
<body>
<p>Hello, World!</p>
</body>
</html>
""";
// String with escape sequences
String path = "C:\\Program Files\\Java";
String quote = "He said, \"Hello!\"";
String newline = "Line 1\nLine 2";
String Immutability
Understanding Immutability
Once a String object is created, its value cannot be changed. Any operation that appears to modify a string actually creates a new string.
java
String original = "Hello";
String modified = original.concat(" World");
System.out.println(original); // Output: "Hello" (unchanged)
System.out.println(modified); // Output: "Hello World" (new object)
Why Strings are Immutable
java
String s1 = "Hello";
String s2 = s1; // Both reference same object
s1 = s1 + " World"; // Creates new object, s2 still references "Hello"
System.out.println(s1); // "Hello World"
System.out.println(s2); // "Hello"
Implications of Immutability
java
// Inefficient concatenation in loops
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Creates new string each time!
}
// Better approach
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String efficientResult = sb.toString();
Basic String Operations
1. Length and Empty Checks
java
String text = "Hello, World!";
int length = text.length(); // 13
boolean isEmpty = text.isEmpty(); // false
boolean isBlank = text.isBlank(); // false (Java 11+)
String emptyStr = "";
System.out.println(emptyStr.isEmpty()); // true
System.out.println(" ".isBlank()); // true (Java 11+)
2. Character Access
java
String str = "Java Programming";
char firstChar = str.charAt(0); // 'J'
char lastChar = str.charAt(str.length() - 1); // 'g'
// Character by character iteration
for (int i = 0; i < str.length(); i++) {
System.out.println("Character at " + i + ": " + str.charAt(i));
}
// Enhanced for loop (convert to char array first)
for (char c : str.toCharArray()) {
System.out.print(c + " ");
}
3. Substring Operations
java
String text = "Hello, World!";
String sub1 = text.substring(7); // "World!" (from index 7 to end)
String sub2 = text.substring(0, 5); // "Hello" (from 0 to 4)
String sub3 = text.substring(7, 12); // "World" (from 7 to 11)
// Common use cases
String filename = "document.pdf";
String nameWithoutExtension = filename.substring(0, filename.lastIndexOf('.'));
4. Case Conversion
java
String mixed = "Hello World";
String upper = mixed.toUpperCase(); // "HELLO WORLD"
String lower = mixed.toLowerCase(); // "hello world"
// Locale-sensitive conversion
String turkish = "istanbul";
String upperTurkish = turkish.toUpperCase(Locale.forLanguageTag("tr"));
String Comparison
1. Reference Comparison (==
)
java
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = new String("Hello");
System.out.println(s1 == s2); // true (same string pool object)
System.out.println(s1 == s3); // false (different objects)
System.out.println(s3 == s4); // false (different objects)
2. Content Comparison (equals()
)
java
String s1 = "Hello";
String s2 = new String("Hello");
String s3 = "HELLO";
System.out.println(s1.equals(s2)); // true (same content)
System.out.println(s1.equals(s3)); // false (different case)
System.out.println(s1.equalsIgnoreCase(s3)); // true (ignore case)
3. Comparison with Ordering
java
String s1 = "apple";
String s2 = "banana";
String s3 = "Apple";
System.out.println(s1.compareTo(s2)); // negative (apple < banana)
System.out.println(s2.compareTo(s1)); // positive (banana > apple)
System.out.println(s1.compareTo(s3)); // positive (apple > Apple - ASCII)
System.out.println(s1.compareToIgnoreCase(s3)); // 0 (equal ignoring case)
4. Advanced Comparison Methods
java
String text = "Hello World";
// Prefix and suffix checks
System.out.println(text.startsWith("Hello")); // true
System.out.println(text.endsWith("World")); // true
System.out.println(text.startsWith("World", 6)); // true (from offset)
// Pattern matching
System.out.println(text.matches(".*World.*")); // true (regex)
String Searching
1. Index-based Searching
java
String text = "Java is fun and Java is powerful";
int firstJava = text.indexOf("Java"); // 0
int secondJava = text.indexOf("Java", 1); // 14 (search from index 1)
int lastJava = text.lastIndexOf("Java"); // 14
int firstA = text.indexOf('a'); // 1
int lastA = text.lastIndexOf('a'); // 18
// Check if contains substring
boolean containsFun = text.contains("fun"); // true
2. Character Searching
java
String text = "Hello World";
// Find first/l occurrence of any character from set
int firstVowel = text.indexOf("aeiou"); // -1 (searches for substring "aeiou")
// Correct way:
int firstVowelPos = -1;
for (char c : text.toCharArray()) {
if ("aeiou".indexOf(c) >= 0) {
firstVowelPos = text.indexOf(c);
break;
}
}
3. Advanced Searching with Regular Expressions
java
String text = "Email: john@example.com, Phone: 123-456-7890";
// Find all email patterns
Pattern emailPattern = Pattern.compile("\\b[\\w.%-]+@[\\w.-]+\\.[A-Z]{2,}\\b", Pattern.CASE_INSENSITIVE);
Matcher matcher = emailPattern.matcher(text);
while (matcher.find()) {
System.out.println("Found email: " + matcher.group());
}
String Modification
1. Concatenation
java
// Using + operator
String s1 = "Hello" + " " + "World"; // "Hello World"
// Using concat() method
String s2 = "Hello".concat(" World"); // "Hello World"
// With different types
String result = "Value: " + 42 + ", PI: " + 3.14; // "Value: 42, PI: 3.14"
// Efficient concatenation for multiple operations
StringBuilder sb = new StringBuilder();
sb.append("Hello").append(" ").append("World");
String efficient = sb.toString();
2. Replacement
java
String text = "I like cats. Cats are cute.";
// Replace all occurrences
String replaced = text.replace("cats", "dogs"); // "I like dogs. Cats are cute."
String replacedAll = text.replaceAll("(?i)cats", "dogs"); // "I like dogs. Dogs are cute." (case-insensitive)
// Replace first occurrence only
String replacedFirst = text.replaceFirst("cats", "dogs"); // "I like dogs. Cats are cute."
// Character replacement
String noSpaces = text.replace(' ', '_'); // "I_like_cats._Cats_are_cute."
3. Trimming and Stripping
java
String padded = " Hello World ";
String trimmed = padded.trim(); // "Hello World" (removes leading/trailing whitespace)
String stripped = padded.strip(); // "Hello World" (Java 11+, better Unicode support)
String leadingStripped = padded.stripLeading(); // "Hello World " (Java 11+)
String trailingStripped = padded.stripTrailing(); // " Hello World" (Java 11+)
4. Splitting and Joining
java
String csv = "apple,banana,orange,grape";
// Split into array
String[] fruits = csv.split(",");
for (String fruit : fruits) {
System.out.println(fruit);
}
// Split with limit
String[] limited = csv.split(",", 2); // ["apple", "banana,orange,grape"]
// Join strings (Java 8+)
String joined = String.join(" - ", fruits); // "apple - banana - orange - grape"
// Multi-line string joining
String lines = String.join("\n", "Line 1", "Line 2", "Line 3");
String Conversion
1. Primitive to String
java
// Various conversion methods
String fromInt = String.valueOf(42); // "42"
String fromDouble = String.valueOf(3.14); // "3.14"
String fromBoolean = String.valueOf(true); // "true"
String fromChar = String.valueOf('A'); // "A"
// Using toString() wrapper classes
String fromInteger = Integer.toString(123); // "123"
String fromDoubleObj = Double.toString(2.718); // "2.718"
2. String to Primitive
java
String numberStr = "123";
String doubleStr = "3.14";
String boolStr = "true";
int intValue = Integer.parseInt(numberStr); // 123
double doubleValue = Double.parseDouble(doubleStr); // 3.14
boolean boolValue = Boolean.parseBoolean(boolStr); // true
// With number format exception handling
try {
int value = Integer.parseInt("123abc");
} catch (NumberFormatException e) {
System.out.println("Invalid number format");
}
3. Character Array Conversion
java
String text = "Hello";
// String to char array
char[] charArray = text.toCharArray();
// Char array to String
String fromArray = new String(charArray);
String valueOfArray = String.valueOf(charArray);
// Partial array conversion
char[] partial = new char[3];
text.getChars(0, 3, partial, 0); // partial = ['H', 'e', 'l']
4. Byte Array Conversion (Encoding)
java
String text = "Hello, World!";
// String to bytes with specific encoding
byte[] utf8Bytes = text.getBytes(StandardCharsets.UTF_8);
byte[] defaultBytes = text.getBytes(); // Platform default encoding
// Bytes to String
String fromBytes = new String(utf8Bytes, StandardCharsets.UTF_8);
// Base64 encoding/decoding (Java 8+)
String encoded = Base64.getEncoder().encodeToString(text.getBytes());
byte[] decoded = Base64.getDecoder().decode(encoded);
String original = new String(decoded);
String Formatting
1. String.format()
Method
java
String name = "John";
int age = 30;
double salary = 45000.50;
// Basic formatting
String message = String.format("Name: %s, Age: %d, Salary: $%.2f", name, age, salary);
System.out.println(message); // "Name: John, Age: 30, Salary: $45000.50"
// Format specifiers
String formatted = String.format("Decimal: %d, Hex: %x, Float: %.3f, String: %s",
255, 255, 3.14159, "Hello");
2. printf()
Style Formatting
java
// Direct output formatting
System.out.printf("Name: %-10s | Age: %03d | Score: %.1f%n", "Alice", 25, 95.5);
// Output: "Name: Alice | Age: 025 | Score: 95.5"
// Common format specifiers
// %s - string, %d - integer, %f - float, %n - newline
// %-10s - left-aligned in 10 characters
// %03d - zero-padded to 3 digits
3. Message Formatting
java
// Complex message formatting
String pattern = "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.";
MessageFormat formatter = new MessageFormat(pattern);
Object[] args = {7, new Date(), "a disturbance in the Force"};
String result = formatter.format(args);
4. Text Block Formatting (Java 15+)
java
// Multi-line string formatting
String html = """
<html>
<body>
<h1>%s</h1>
<p>Age: %d</p>
<p>Salary: $%.2f</p>
</body>
</html>
""".formatted(name, age, salary);
Performance Considerations
1. String Concatenation in Loops
java
// ❌ Inefficient - creates new string each iteration
String result = "";
for (int i = 0; i < 1000; i++) {
result += i; // Creates 1000+ string objects!
}
// ✅ Efficient - uses StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(i);
}
String efficientResult = sb.toString();
2. String Pool Benefits
java
// ✅ Use string literals when possible
String s1 = "hello"; // Uses string pool
String s2 = "hello"; // Reuses same object
// ❌ Avoid unnecessary new String()
String s3 = new String("hello"); // Creates new object unnecessarily
3. Memory Efficient Operations
java
// For large string manipulations
String largeText = "Very long text...";
// Use substring carefully (Java 7+ shares char array, but still)
String part = largeText.substring(0, 10);
// For repeated modifications, use StringBuilder/Buffer
StringBuilder builder = new StringBuilder(largeText);
builder.append(" additional content");
String modified = builder.toString();
Common Mistakes and Best Practices
Common Mistakes
Using
==
for content comparisonjavaString s1 = "hello"; String s2 = new String("hello"); // ❌ Wrong if (s1 == s2) { /* never true */ } // ✅ Correct if (s1.equals(s2)) { /* true */ }
Ignoring case in comparisons
javaString input = "YES"; // ❌ May fail if (input.equals("yes")) { /* false */ } // ✅ Better if (input.equalsIgnoreCase("yes")) { /* true */ }
Inefficient string building
java// ❌ Inefficient String sql = "SELECT * FROM users"; sql += " WHERE age > 18"; sql += " AND status = 'active'"; // ✅ Efficient StringBuilder sqlBuilder = new StringBuilder("SELECT * FROM users"); sqlBuilder.append(" WHERE age > 18"); sqlBuilder.append(" AND status = 'active'"); String sql = sqlBuilder.toString();
Best Practices
Use string literals for constants
java// ✅ Good private static final String DEFAULT_NAME = "Unknown"; // Use StringBuilder for complex building StringBuilder pathBuilder = new StringBuilder(); pathBuilder.append(basePath).append("/").append(fileName); String fullPath = pathBuilder.toString();
Handle null safely
javaString input = possiblyNullString; // Safe comparison if ("expected".equals(input)) { /* handles null */ } // Safe conversion String safe = input == null ? "" : input;
Use appropriate string methods
java// Check empty strings if (str != null && !str.isEmpty()) { /* modern */ } if (str != null && str.length() > 0) { /* traditional */ } // Trim and check if (str != null && !str.trim().isEmpty()) { /* handles whitespace */ }
Summary
- Strings are immutable objects in Java
- Use
equals()
for content comparison, not==
StringBuilder
is more efficient for multiple modifications- String pool optimizes memory usage for literals
- Java provides rich set of string manipulation methods
- Always consider performance for string operations in loops
- Handle null values and encoding properly
In the next section, we'll explore the comprehensive set of String methods available in Java for various operations.