TechByteByByte

Remove All Occurrences of a Given Character from a String - Java

An easy QA/automation coding interview question: remove All Occurrences of a Given Character from a String, with a full Java walkthrough, dry run, and common interviewer follow-ups.

#Strings#StringBuilder#Easy#Java

Category: Easy | Concepts used: String buffer filtering, character comparison, String immutability


Problem Statement

Given a string and a target character, remove every occurrence of that character.

Input : str = "banana", ch = 'a'      Output: "bnn"
Input : str = "hello", ch = 'z'         Output: "hello"   (unchanged)

Examples (with edge scenarios)

#strchOutputWhy
1"banana"'a'"bnn"All 3 'a's are removed
2"hello"'z'"hello"'z' is not present
3""'x'""Empty string yields empty output
4"aaaa"'a'""All characters match target, leaving empty
5"Banana"'a'"Bnn"Case-sensitive mismatch (only 'a' is removed, 'B' remains)

⚠️ Common Beginner Mistake

MistakeImpactFix
Replacing with a space (ch = ' ') instead of empty spaceLeaves empty character gaps in the middle of wordsAccumulate only matching indices to shrink the string
Using replaceAll on literal characters without escapingCharacters like . or * are parsed as regex controls, corrupting the resultUse replace(String.valueOf(ch), "") for safe literal swaps

Before You Code: Clarify the Contract

Before choosing an algorithm, confirm how null and empty strings should behave, whether comparison is case-sensitive, and whether spaces or punctuation count. Java char values are UTF-16 code units, not always complete human-visible Unicode characters, so international text may require code points or grapheme-aware libraries.

Analogy: Conveyor Belt Quality Inspector

Imagine you are an inspector at a manufacturing line:

  • You are looking at a conveyor belt of items (the string).
  • You are instructed: “Remove all cracked cups (the target character) from the line.”
  • You inspect each item:
    • If it is a cracked cup, you discard it (skip it).
    • If it is any other clean item, you place it on the shipping tray (result.append(ch)).
  • The shipping tray ends up containing only clean, uncracked items!

Solution 1 — Loop + StringBuilder (Optimal Manual)

This is the standard manual approach using a mutable string buffer.

Intuition

We traverse the string, comparing each character to the target. We append to our StringBuilder only when the character does not match, avoiding intermediate string copy operations.

public class RemoveCharOccurrences {
    public static String removeChar(String str, char target) {
        if (str == null || str.isEmpty()) {
            return str;
        }

StringBuilder result = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char ch = str.charAt(i);
            if (ch != target) { // Only append if it is not the target
                result.append(ch);
            }
        }
        return result.toString();
    }

public static void main(String[] args) {
        System.out.println(removeChar("banana", 'a')); // "bnn"
        System.out.println(removeChar("hello", 'z'));   // "hello"
        System.out.println(removeChar("aaaa", 'a'));     // ""
        System.out.println(removeChar("", 'x'));          // ""
    }
}

Output:

bnn
hello

Solution 2 — Using String.replace() (Concise & Literal)

This is the preferred built-in helper method.

Intuition

While Java doesn’t have a direct character-based removal method, we can convert the target character into a single-character string using String.valueOf() and call str.replace(). In Java, replace() replaces all literal matches without regular expression compilation.

public class RemoveCharReplace {
    public static String removeChar(String str, char target) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        // String.valueOf(target) converts the char to a String sequence
        return str.replace(String.valueOf(target), "");
    }

public static void main(String[] args) {
        System.out.println(removeChar("banana", 'a')); // "bnn"
    }
}

Output:

bnn

📊 Visual Flowchart

graph TD
    Start["Input String S, target char T"] --> NullCheck{"S is null?"}
    NullCheck -->|Yes| RetNull["Return Null"]
    NullCheck -->|No| InitBuilder["Initialize StringBuilder sb"]
    InitBuilder --> Loop{"i < S.length()?"}
    Loop -->|Yes| Fetch["ch = S.charAt(i)"]
    Fetch --> CheckTarget{"ch == T?"}
    CheckTarget -->|Yes| Skip["i++"]
    CheckTarget -->|No| Append["sb.append(ch)"]
    Append --> Skip
    Skip --> Loop
    Loop -->|No| Convert["sb.toString()"]
    Convert --> End["Return result"]

Interviewer Insights

This question tests basic flow control, heap memory limits, and API scope.

Follow-up questions you might get:

  • “What is the difference between String.replace() and String.replaceAll()?”
    • replace() performs literal string replacements. It converts inputs into CharSequences and scans characters.
    • replaceAll() treats the input target as a regular expression.
    • Interview Tip: Proactively state that using replaceAll to remove a single character like . without escaping it (str.replaceAll(".", "")) will empty the entire string, since . matches any character in regex. replace(".", "") is safe.
  • “How would you count how many characters were removed?” → Subtract the lengths: str.length() - result.length().

Quick Recap

ApproachTime ComplexityAuxiliary Space ComplexityRegex Overhead?Interview Signal
StringBuilder Loop(O(N))(O(N))NoStandard loop construction, memory-conscious
replace(charString, "")(O(N))(O(N))NoConcise literal replacement, clean API usage
replaceAll(regex, "")(O(N))(O(N))YesOverkill for simple characters, prone to regex special-char bugs
Author
TechByteByByte Editorial Team
Reviewed by
TechByteByByte Admin
Published
Last reviewed