Skip to content

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

  1. Using == for content comparison

    java
    String s1 = "hello";
    String s2 = new String("hello");
    
    // ❌ Wrong
    if (s1 == s2) { /* never true */ }
    
    // ✅ Correct
    if (s1.equals(s2)) { /* true */ }
  2. Ignoring case in comparisons

    java
    String input = "YES";
    
    // ❌ May fail
    if (input.equals("yes")) { /* false */ }
    
    // ✅ Better
    if (input.equalsIgnoreCase("yes")) { /* true */ }
  3. 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

  1. 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();
  2. Handle null safely

    java
    String input = possiblyNullString;
    
    // Safe comparison
    if ("expected".equals(input)) { /* handles null */ }
    
    // Safe conversion
    String safe = input == null ? "" : input;
  3. 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.