Java String

What is a String?

A String in Java is a sequence of characters used to represent text. It is one of the most commonly used data types in any Java program. Whether you are storing a user’s name, reading data from a file, building SQL queries, or formatting output, you are working with Strings.

Key facts about Java Strings:

  • Reference type, not a primitive — String is a class (java.lang.String), not a primitive like int or char. A String variable holds a reference to an object on the heap.
  • Immutable — Once a String object is created, its character content can never be changed. Every operation that appears to modify a String actually creates a new String object.
  • Backed by a char array (or byte array since Java 9) — Internally, a String stores its characters in an array. Since Java 9, it uses a compact byte[] with an encoding flag for memory efficiency.
  • Implements CharSequence, Comparable<String>, and Serializable — This means Strings can be compared, sorted, and transmitted across networks or saved to files natively.

In Java, String literals are enclosed in double quotes ("Hello"). Single quotes are reserved for the char primitive type ('H').

// String -- a sequence of characters in double quotes
String greeting = "Hello, World!";
System.out.println(greeting);        // Hello, World!
System.out.println(greeting.length()); // 13

// char -- a single character in single quotes
char letter = 'A';

// This will NOT compile -- single quotes are for char, not String
// String wrong = 'Hello';  // Compilation error!

Creating Strings

There are two ways to create a String in Java, and the difference between them matters for both memory usage and object identity.

1. String Literal (String Pool)

When you create a String using a literal (double quotes), Java checks a special memory area called the String Pool (also known as the String Intern Pool). If an identical String already exists in the pool, Java returns a reference to that existing object instead of creating a new one. If no match is found, a new String object is created in the pool.

// Both variables point to the SAME object in the String Pool
String a = "Hello";
String b = "Hello";

// Since they reference the same object, == returns true
System.out.println(a == b); // true

2. Using the new Keyword (Heap Allocation)

When you use the new keyword, Java always creates a new String object on the heap, even if an identical String already exists in the pool. This means two Strings with the same content can be different objects in memory.

// Forces a new object on the heap, bypassing the String Pool
String c = new String("Hello");
String d = new String("Hello");

// Different objects in memory, so == returns false
System.out.println(c == d);    // false

// But their content is the same, so equals() returns true
System.out.println(c.equals(d)); // true

Memory Diagram: Literal vs new

Here is what happens in memory when you create Strings both ways:

  Stack                    Heap
  ------                   ------
  a ----+
        |---> [ "Hello" ]  <-- String Pool
  b ----+

  c ----------> [ "Hello" ]  <-- new object on heap (not in pool)
  d ----------> [ "Hello" ]  <-- another new object on heap

Best practice: Always use String literals unless you have a specific reason to use new String(). Literals benefit from the String Pool, which saves memory and enables faster comparisons.

String Immutability

Immutability means that once a String object is created, its contents cannot be changed. There is no method on String that modifies the original object. Every method that seems to change a String (like toUpperCase(), replace(), concat()) actually returns a new String object.

String original = "Hello";
String modified = original.toUpperCase();

System.out.println(original); // Hello  -- the original is unchanged!
System.out.println(modified); // HELLO  -- a brand new String object

// The variable can be reassigned, but the String object "Hello" still exists
String name = "Folau";
name = "Lisa";
// "Folau" is still in the String Pool -- we just moved the reference
// name now points to a different String object "Lisa"

Why Immutability Matters

String immutability is a deliberate design decision in Java, and it provides three major benefits:

  1. Thread Safety — Because Strings cannot be modified, they can be shared freely between threads without synchronization. No thread can corrupt a String that another thread is reading.
  2. Security — Strings are used for class loading, network connections, file paths, and database URLs. If Strings were mutable, malicious code could alter a validated file path or network address after security checks have passed.
  3. Caching and Performance — Because a String’s content never changes, its hash code can be computed once and cached. This makes Strings extremely efficient as keys in HashMap and HashSet. The String Pool itself is only possible because of immutability.

The String Pool (Intern Pool)

The String Pool is a special area of the heap where Java stores String literals. It is an optimization that prevents creating duplicate String objects for the same content.

How the pool works:

  1. When your code contains a String literal like "Hello", the JVM checks the pool.
  2. If "Hello" already exists in the pool, the JVM returns a reference to the existing object.
  3. If not, a new String is created in the pool and the reference is returned.

You can manually add a heap-allocated String to the pool using the intern() method:

String heapString = new String("Hello"); // created on the heap
String poolString = "Hello";              // from the String Pool

System.out.println(heapString == poolString);           // false -- different objects

// intern() returns a reference to the pool's copy
String internedString = heapString.intern();
System.out.println(internedString == poolString);       // true -- same pool object
System.out.println(internedString.equals(poolString));  // true

Note: In modern Java, the String Pool lives in the main heap (since Java 7), not in the PermGen space. This means it can grow dynamically and is subject to garbage collection. You rarely need to call intern() explicitly — the JVM handles it for literals automatically.

String Comparison (Critical Topic)

String comparison is one of the most common sources of bugs for Java beginners. The key rule to remember is: use equals() for content comparison, never ==.

== vs equals()

Operator/Method What it compares Use case
== Object references (memory addresses) Rarely useful for Strings
equals() Character-by-character content Almost always what you want
equalsIgnoreCase() Content, ignoring upper/lower case Case-insensitive matching
String literal1 = "Hello";
String literal2 = "Hello";
String heapStr  = new String("Hello");

// == compares references (memory addresses)
System.out.println(literal1 == literal2); // true  -- same pool object
System.out.println(literal1 == heapStr);  // false -- different objects

// equals() compares content
System.out.println(literal1.equals(literal2)); // true
System.out.println(literal1.equals(heapStr));  // true

// equalsIgnoreCase() ignores case
String upper = "HELLO";
System.out.println(literal1.equalsIgnoreCase(upper)); // true
System.out.println(literal1.equals(upper));            // false

Common bug: User input from Scanner, HTTP requests, file reads, and database queries always creates new String objects on the heap. Using == on these will almost always return false, even when the text matches. Always use equals().

compareTo() for Ordering

The compareTo() method compares two Strings lexicographically (dictionary order). It returns:

  • 0 if the strings are equal
  • A negative number if the calling string comes before the argument
  • A positive number if the calling string comes after the argument
String apple  = "apple";
String banana = "banana";
String cherry = "cherry";

System.out.println(apple.compareTo(banana));  // negative (a < b)
System.out.println(banana.compareTo(apple));  // positive (b > a)
System.out.println(apple.compareTo(apple));   // 0 (equal)

// compareToIgnoreCase() ignores case
String upper = "APPLE";
System.out.println(apple.compareToIgnoreCase(upper)); // 0

// compareTo() is used for sorting
List<String> fruits = Arrays.asList("cherry", "apple", "banana");
Collections.sort(fruits); // uses compareTo() internally
System.out.println(fruits); // [apple, banana, cherry]

Essential String Methods

The String class provides dozens of useful methods. Here are the most important ones every Java developer should know, organized by category.

Length and Character Access

length() returns the number of characters. charAt(int index) returns the character at a specific position (zero-indexed). toCharArray() converts the entire String to a char[].

String name = "Folau";

// length() -- number of characters
System.out.println(name.length()); // 5

// charAt() -- character at index (0-based)
System.out.println(name.charAt(0)); // F
System.out.println(name.charAt(4)); // u

// toCharArray() -- convert to char array
char[] chars = name.toCharArray();
for (char c : chars) {
    System.out.print(c + " "); // F o l a u
}
System.out.println();

// Looping through characters
for (int i = 0; i < name.length(); i++) {
    System.out.println("Index " + i + ": " + name.charAt(i));
}
// Index 0: F
// Index 1: o
// Index 2: l
// Index 3: a
// Index 4: u

Searching: indexOf(), lastIndexOf(), contains()

indexOf() returns the position of the first occurrence of a character or substring, or -1 if not found. lastIndexOf() searches from the end. contains() returns a simple boolean.

String sentence = "Java is powerful and Java is everywhere";

// indexOf() -- first occurrence
System.out.println(sentence.indexOf("Java"));    // 0
System.out.println(sentence.indexOf("Java", 1)); // 24 (search from index 1)
System.out.println(sentence.indexOf("Python"));  // -1 (not found)

// lastIndexOf() -- last occurrence
System.out.println(sentence.lastIndexOf("Java")); // 24

// contains() -- boolean check
System.out.println(sentence.contains("powerful")); // true
System.out.println(sentence.contains("weak"));     // false

// startsWith() and endsWith()
String url = "https://lovemesomecoding.com/java";
System.out.println(url.startsWith("https")); // true
System.out.println(url.endsWith(".com/java")); // true
System.out.println(url.startsWith("java", 8)); // false

Extracting: substring()

substring(int beginIndex) returns everything from beginIndex to the end. substring(int beginIndex, int endIndex) returns from beginIndex up to (but not including) endIndex.

String text = "Hello, World!";

// substring(beginIndex) -- from index to end
System.out.println(text.substring(7));    // World!

// substring(beginIndex, endIndex) -- from begin up to (not including) end
System.out.println(text.substring(0, 5)); // Hello
System.out.println(text.substring(7, 12)); // World

// Practical example: extract domain from email
String email = "folau@lovemesomecoding.com";
String domain = email.substring(email.indexOf("@") + 1);
System.out.println(domain); // lovemesomecoding.com

// Extract file extension
String filename = "report.pdf";
String extension = filename.substring(filename.lastIndexOf(".") + 1);
System.out.println(extension); // pdf

Concatenation: concat() and join()

concat() appends one String to another. String.join() is a static method that joins multiple Strings with a delimiter between them. Both return new String objects.

// concat() -- appends a string
String first = "Folau";
String last = "Kaveinga";
String fullName = first.concat(" ").concat(last);
System.out.println(fullName); // Folau Kaveinga

// The + operator does the same thing
String fullName2 = first + " " + last;
System.out.println(fullName2); // Folau Kaveinga

// String.join() -- joins with a delimiter
String csv = String.join(", ", "Java", "Python", "JavaScript");
System.out.println(csv); // Java, Python, JavaScript

// join() with a List
List<String> items = Arrays.asList("apple", "banana", "cherry");
String joined = String.join(" | ", items);
System.out.println(joined); // apple | banana | cherry

// Building a file path
String path = String.join("/", "home", "user", "documents", "file.txt");
System.out.println(path); // home/user/documents/file.txt

Replacing: replace() and replaceAll()

replace() replaces all occurrences of a character or exact substring. replaceAll() takes a regular expression pattern, giving you more powerful replacements. replaceFirst() replaces only the first match.

String text = "Java is great. Java is powerful.";

// replace() -- replaces exact matches (all occurrences)
System.out.println(text.replace("Java", "Python"));
// Python is great. Python is powerful.

// replace() with char
System.out.println("hello".replace('l', 'r')); // herro

// replaceAll() -- uses regex pattern
String messy = "Hello   World   Java";
System.out.println(messy.replaceAll("\\s+", " ")); // Hello World Java

// Remove all non-alphanumeric characters
String dirty = "Hello! @World# 123";
System.out.println(dirty.replaceAll("[^a-zA-Z0-9 ]", "")); // Hello World 123

// replaceFirst() -- only first match
System.out.println(text.replaceFirst("Java", "Python"));
// Python is great. Java is powerful.

Splitting: split()

split(String regex) divides a String into an array of substrings based on a delimiter pattern. This is one of the most useful methods for parsing data.

// Basic split with comma
String csv = "Java,Python,JavaScript,Go";
String[] languages = csv.split(",");
for (String lang : languages) {
    System.out.println(lang);
}
// Java
// Python
// JavaScript
// Go

// Split with limit -- maximum number of pieces
String[] limited = csv.split(",", 2);
System.out.println(limited[0]); // Java
System.out.println(limited[1]); // Python,JavaScript,Go

// Split on whitespace (handles multiple spaces)
String sentence = "Hello   World   Java";
String[] words = sentence.split("\\s+");
System.out.println(Arrays.toString(words)); // [Hello, World, Java]

// Split on pipe (pipe is a regex special char, must escape)
String data = "name|age|city";
String[] fields = data.split("\\|");
System.out.println(Arrays.toString(fields)); // [name, age, city]

// Practical example: parse a CSV line
String record = "Folau,Kaveinga,folau@email.com,35";
String[] parts = record.split(",");
String firstName = parts[0]; // Folau
String lastName  = parts[1]; // Kaveinga
String email     = parts[2]; // folau@email.com
int age          = Integer.parseInt(parts[3]); // 35

Trimming: trim() and strip()

trim() removes leading and trailing whitespace characters (ASCII value <= 32). strip(), introduced in Java 11, removes leading and trailing whitespace including Unicode whitespace characters, making it the preferred choice in modern Java.

String padded = "   Hello, World!   ";

// trim() -- removes ASCII whitespace from both ends
System.out.println("[" + padded.trim() + "]"); // [Hello, World!]

// strip() -- Java 11+ (handles Unicode whitespace too)
System.out.println("[" + padded.strip() + "]"); // [Hello, World!]

// stripLeading() -- only the beginning
System.out.println("[" + padded.stripLeading() + "]"); // [Hello, World!   ]

// stripTrailing() -- only the end
System.out.println("[" + padded.stripTrailing() + "]"); // [   Hello, World!]

// Practical difference: Unicode whitespace
String unicode = "\u2000 Hello \u2000"; // Unicode "En Quad" space
System.out.println("[" + unicode.trim() + "]");  // [ Hello  ] -- trim misses it
System.out.println("[" + unicode.strip() + "]"); // [Hello]    -- strip catches it

Case Conversion: toUpperCase() and toLowerCase()

String mixed = "Hello World";

System.out.println(mixed.toUpperCase()); // HELLO WORLD
System.out.println(mixed.toLowerCase()); // hello world

// Useful for case-insensitive comparison without equalsIgnoreCase
String input = "YES";
if (input.toLowerCase().equals("yes")) {
    System.out.println("User confirmed"); // User confirmed
}

// Locale-aware conversion (important for Turkish, German, etc.)
String turkish = "TITLE";
System.out.println(turkish.toLowerCase(Locale.forLanguageTag("tr"))); // tıtle (note dotless i)

Formatting: format() and formatted()

String.format() works like C’s printf. It uses format specifiers (%s for string, %d for integer, %f for floating point, %n for newline) to build formatted output. Java 15 introduced the formatted() instance method as a shorthand.

// String.format() -- static method
String name = "Folau";
int age = 30;
double gpa = 3.85;

String info = String.format("Name: %s, Age: %d, GPA: %.1f", name, age, gpa);
System.out.println(info); // Name: Folau, Age: 30, GPA: 3.9

// Common format specifiers:
// %s  -- String
// %d  -- integer (decimal)
// %f  -- floating point
// %.2f -- floating point with 2 decimal places
// %n  -- platform-specific newline
// %10s -- right-padded to 10 characters
// %-10s -- left-padded to 10 characters

// Formatting a table
String header = String.format("%-15s %-10s %10s", "Name", "Language", "Years");
String row1   = String.format("%-15s %-10s %10d", "Folau", "Java", 10);
String row2   = String.format("%-15s %-10s %10d", "Lisa", "Python", 5);
System.out.println(header);
System.out.println(row1);
System.out.println(row2);
// Name            Language        Years
// Folau           Java               10
// Lisa            Python              5

// formatted() -- Java 15+ instance method (same thing, shorter syntax)
String message = "Hello, %s! You have %d new messages.".formatted(name, 5);
System.out.println(message); // Hello, Folau! You have 5 new messages.

Empty and Blank Checks: isEmpty() and isBlank()

isEmpty() returns true if the String has zero length. isBlank() (Java 11+) returns true if the String is empty OR contains only whitespace characters. This distinction is important for input validation.

String empty      = "";
String blank      = "   ";
String hasContent = "Hello";

// isEmpty() -- true if length is 0
System.out.println(empty.isEmpty());      // true
System.out.println(blank.isEmpty());      // false  -- has spaces
System.out.println(hasContent.isEmpty()); // false

// isBlank() -- Java 11+ -- true if empty OR only whitespace
System.out.println(empty.isBlank());      // true
System.out.println(blank.isBlank());      // true   -- only whitespace
System.out.println(hasContent.isBlank()); // false

// Practical input validation
public static boolean isValidInput(String input) {
    return input != null && !input.isBlank();
}

// Always check for null first!
String userInput = null;
// userInput.isEmpty();  // NullPointerException!
// Safe approach:
if (userInput != null && !userInput.isBlank()) {
    System.out.println("Valid input");
} else {
    System.out.println("Invalid input"); // Invalid input
}

String Concatenation Performance

Because Strings are immutable, every concatenation with the + operator creates a new String object. For a few concatenations, this is fine. But inside a loop, it becomes a serious performance problem because the JVM creates and discards many temporary String objects.

Java provides two mutable alternatives for building Strings efficiently:

Class Thread-Safe? Performance When to Use
String with + Yes (immutable) Slow in loops Simple, small concatenations
StringBuilder No Fast Building strings in loops (single-threaded)
StringBuffer Yes (synchronized) Slightly slower Building strings in loops (multi-threaded)
// BAD: String concatenation in a loop
// Each += creates a new String object, copies all previous characters, then discards the old one
String result = "";
for (int i = 0; i < 10000; i++) {
    result += i + ", ";  // Creates ~10,000 temporary String objects!
}
// For 10,000 iterations, this copies roughly 50 million characters total


// GOOD: StringBuilder -- mutable, no unnecessary copies
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i).append(", ");
}
String result2 = sb.toString();
// Uses a single internal buffer that grows as needed -- much faster


// StringBuffer -- same API, but thread-safe (synchronized)
StringBuffer sbuf = new StringBuffer();
for (int i = 0; i < 10000; i++) {
    sbuf.append(i).append(", ");
}
String result3 = sbuf.toString();

Performance Comparison

// Simple benchmark to demonstrate the difference
int iterations = 100_000;

// String concatenation with +
long start = System.currentTimeMillis();
String s = "";
for (int i = 0; i < iterations; i++) {
    s += "a";
}
long stringTime = System.currentTimeMillis() - start;

// StringBuilder
start = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < iterations; i++) {
    sb.append("a");
}
String s2 = sb.toString();
long builderTime = System.currentTimeMillis() - start;

System.out.println("String +:      " + stringTime + " ms");   // ~3000-5000 ms
System.out.println("StringBuilder: " + builderTime + " ms");  // ~2-5 ms
// StringBuilder is roughly 1000x faster for large loops!

Rule of thumb: Use + for simple, one-line concatenations. Use StringBuilder whenever you are building a String inside a loop or across many steps. Use StringBuffer only when multiple threads are appending to the same builder simultaneously (this is rare).

Note: The Java compiler automatically converts simple + concatenation (outside loops) into StringBuilder calls. Since Java 9, it uses invokedynamic for even better optimization. So String a = first + " " + last; is already efficient — the concern is specifically about loops.

Text Blocks (Java 13+)

Text Blocks, introduced as a preview in Java 13 and finalized in Java 15, allow you to write multi-line String literals using triple double-quotes ("""). They eliminate the need for escape sequences and string concatenation when working with multi-line text like JSON, SQL, HTML, or XML.

// BEFORE text blocks -- messy and error-prone
String jsonOld = "{\n" +
    "  \"name\": \"Folau\",\n" +
    "  \"age\": 30,\n" +
    "  \"language\": \"Java\"\n" +
    "}";

// AFTER text blocks -- clean and readable
String jsonNew = """
        {
          "name": "Folau",
          "age": 30,
          "language": "Java"
        }
        """;
System.out.println(jsonNew);

Text Block Rules

  • The opening """ must be followed by a line break — no content on the same line.
  • The closing """ determines the indentation baseline. Content indented beyond it is preserved; content aligned with it has no leading whitespace.
  • Single and double quotes do not need escaping inside text blocks.
  • Use \ (backslash at end of line) to suppress the newline at that point — this is a line continuation character.
  • Use \s to preserve trailing whitespace that would otherwise be stripped.
// SQL query -- much cleaner with text blocks
String sql = """
        SELECT u.name, u.email, o.total
        FROM users u
        JOIN orders o ON u.id = o.user_id
        WHERE o.total > 100
        ORDER BY o.total DESC
        """;

// HTML template
String html = """
        <html>
          <body>
            <h1>Welcome</h1>
            <p>Hello, World!</p>
          </body>
        </html>
        """;

// Line continuation with \ (no newline inserted)
String singleLine = """
        This is actually \
        a single line \
        of text.""";
System.out.println(singleLine);
// This is actually a single line of text.

// Text blocks work with format() and formatted()
String template = """
        Dear %s,
        Your order #%d has been shipped.
        Expected delivery: %s
        """.formatted("Folau", 12345, "March 15, 2026");
System.out.println(template);

Common Mistakes and Best Practices

Mistake 1: Comparing Strings with ==

This is the number one String bug in Java. Always use equals() for content comparison.

// BAD -- works sometimes by accident (String Pool), fails with user input
String input = scanner.nextLine();
if (input == "yes") {  // WRONG -- compares references, not content
    // This will almost always be false even if user types "yes"
}

// GOOD -- always compare content
if (input.equals("yes")) {
    // Correct!
}

// BETTER -- put the literal first to avoid NullPointerException
if ("yes".equals(input)) {
    // Safe even if input is null
}

Mistake 2: Ignoring the Return Value of String Methods

Since Strings are immutable, methods like trim(), replace(), and toUpperCase() return a new String. The original is unchanged. You must capture the return value.

// BAD -- the result is thrown away
String name = "  Folau  ";
name.trim();           // returns a new String, but we ignore it
name.toUpperCase();    // same problem
System.out.println(name); // "  Folau  " -- unchanged!

// GOOD -- capture the return value
String name2 = "  Folau  ";
name2 = name2.trim();
name2 = name2.toUpperCase();
System.out.println(name2); // "FOLAU"

// Or chain the methods
String result = "  Folau  ".trim().toUpperCase();
System.out.println(result); // "FOLAU"

Mistake 3: NullPointerException on String Methods

Calling any method on a null reference throws a NullPointerException. Always check for null or use a defensive pattern.

String value = null;

// BAD -- crashes at runtime
// value.length();  // NullPointerException!

// GOOD -- null check first
if (value != null && value.length() > 0) {
    System.out.println(value);
}

// GOOD -- use Objects.requireNonNullElse() (Java 9+)
String safe = java.util.Objects.requireNonNullElse(value, "default");
System.out.println(safe); // default

// GOOD -- put literal first for equals()
if ("expected".equals(value)) {
    // Safe -- "expected" is never null
}

Mistake 4: String Concatenation in Loops

As covered in the performance section, using += in a loop creates many unnecessary objects. Use StringBuilder instead.

Best Practices Summary

  1. Use equals(), not ==, for String comparison. Put the literal on the left side: "value".equals(variable).
  2. Use StringBuilder for concatenation inside loops.
  3. Use isBlank() instead of isEmpty() for input validation (Java 11+).
  4. Use strip() instead of trim() for Unicode-correct whitespace removal (Java 11+).
  5. Use Text Blocks for multi-line strings like SQL, JSON, and HTML (Java 15+).
  6. Use String.format() or formatted() instead of complex + concatenation for readability.
  7. Always check for null before calling String methods.
  8. Prefer String literals over new String() to take advantage of the String Pool.

Real-World Examples

Here are practical examples that demonstrate how String methods are used together in real applications.

Example 1: Parsing and Validating an Email Address

public static boolean isValidEmail(String email) {
    if (email == null || email.isBlank()) {
        return false;
    }

    email = email.strip().toLowerCase();

    // Must contain exactly one @
    int atIndex = email.indexOf("@");
    if (atIndex <= 0 || atIndex != email.lastIndexOf("@")) {
        return false;
    }

    // Must have a domain with a dot
    String domain = email.substring(atIndex + 1);
    if (!domain.contains(".") || domain.startsWith(".") || domain.endsWith(".")) {
        return false;
    }

    return true;
}

// Test
System.out.println(isValidEmail("folau@email.com"));    // true
System.out.println(isValidEmail("invalid@"));            // false
System.out.println(isValidEmail("no-at-sign.com"));      // false
System.out.println(isValidEmail("  FOLAU@Email.COM  ")); // true

Example 2: Converting a String to Title Case

public static String toTitleCase(String input) {
    if (input == null || input.isBlank()) {
        return input;
    }

    String[] words = input.strip().toLowerCase().split("\\s+");
    StringBuilder result = new StringBuilder();

    for (String word : words) {
        if (!result.isEmpty()) {
            result.append(" ");
        }
        // Capitalize first letter, keep rest lowercase
        result.append(Character.toUpperCase(word.charAt(0)));
        result.append(word.substring(1));
    }

    return result.toString();
}

System.out.println(toTitleCase("hello world"));          // Hello World
System.out.println(toTitleCase("jAVA STRING tutorial")); // Java String Tutorial
System.out.println(toTitleCase("  multiple   spaces ")); // Multiple Spaces

Example 3: Building a URL with Query Parameters

public static String buildUrl(String baseUrl, Map<String, String> params) {
    if (params == null || params.isEmpty()) {
        return baseUrl;
    }

    StringBuilder url = new StringBuilder(baseUrl);
    url.append("?");

    boolean first = true;
    for (Map.Entry<String, String> entry : params.entrySet()) {
        if (!first) {
            url.append("&");
        }
        url.append(entry.getKey())
           .append("=")
           .append(entry.getValue());
        first = false;
    }

    return url.toString();
}

// Usage
Map<String, String> params = new LinkedHashMap<>();
params.put("q", "java+string");
params.put("page", "1");
params.put("lang", "en");

String url = buildUrl("https://example.com/search", params);
System.out.println(url);
// https://example.com/search?q=java+string&page=1&lang=en

Example 4: Masking Sensitive Data

public static String maskCreditCard(String cardNumber) {
    // Remove any spaces or dashes
    String cleaned = cardNumber.replaceAll("[\\s-]", "");

    if (cleaned.length() < 4) {
        return "****";
    }

    // Show only last 4 digits
    String lastFour = cleaned.substring(cleaned.length() - 4);
    String masked = "*".repeat(cleaned.length() - 4) + lastFour;

    // Format in groups of 4
    StringBuilder formatted = new StringBuilder();
    for (int i = 0; i < masked.length(); i++) {
        if (i > 0 && i % 4 == 0) {
            formatted.append(" ");
        }
        formatted.append(masked.charAt(i));
    }

    return formatted.toString();
}

System.out.println(maskCreditCard("4532 1234 5678 9012"));
// **** **** **** 9012

System.out.println(maskCreditCard("1234-5678-9012-3456"));
// **** **** **** 3456

Example 5: Parsing a Log Line

// Parse a typical log format: "2026-02-28 10:30:45 [ERROR] NullPointerException in UserService.java:42"
public static void parseLogLine(String logLine) {
    // Split into parts
    String date = logLine.substring(0, 10);                  // 2026-02-28
    String time = logLine.substring(11, 19);                 // 10:30:45

    // Extract log level between [ and ]
    int levelStart = logLine.indexOf("[") + 1;
    int levelEnd   = logLine.indexOf("]");
    String level   = logLine.substring(levelStart, levelEnd); // ERROR

    // Extract message after "] "
    String message = logLine.substring(levelEnd + 2);         // NullPointerException in UserService.java:42

    System.out.println("Date:    " + date);
    System.out.println("Time:    " + time);
    System.out.println("Level:   " + level);
    System.out.println("Message: " + message);

    // Check severity
    if ("ERROR".equals(level) || "FATAL".equals(level)) {
        System.out.println("ALERT: High severity issue detected!");
    }
}

parseLogLine("2026-02-28 10:30:45 [ERROR] NullPointerException in UserService.java:42");
// Date:    2026-02-28
// Time:    10:30:45
// Level:   ERROR
// Message: NullPointerException in UserService.java:42
// ALERT: High severity issue detected!

String Methods Quick Reference

Method Returns Description
length() int Number of characters
charAt(int) char Character at index
indexOf(String) int First index of substring, or -1
lastIndexOf(String) int Last index of substring, or -1
substring(int, int) String Portion of the string
contains(CharSequence) boolean Whether it contains the sequence
startsWith(String) boolean Whether it starts with prefix
endsWith(String) boolean Whether it ends with suffix
equals(Object) boolean Content equality
equalsIgnoreCase(String) boolean Case-insensitive equality
compareTo(String) int Lexicographic comparison
concat(String) String Appends a string
replace(old, new) String Replaces all occurrences
replaceAll(regex, new) String Regex-based replacement
split(regex) String[] Splits into array
trim() String Removes ASCII whitespace
strip() String Removes Unicode whitespace (Java 11+)
toUpperCase() String All uppercase
toLowerCase() String All lowercase
isEmpty() boolean True if length is 0
isBlank() boolean True if empty or only whitespace (Java 11+)
toCharArray() char[] Converts to character array
format(String, Object...) String Printf-style formatting
formatted(Object...) String Instance format method (Java 15+)
join(delim, elements) String Joins elements with delimiter
repeat(int) String Repeats string N times (Java 11+)
intern() String Returns pool reference



Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


Leave a Reply

Your email address will not be published. Required fields are marked *