Remove Special Characters from a String in Java
Problem
A special character is anything that isn't a letter, digit, or whitespace — punctuation and symbols like @, #, or !.
Given a string, remove every special character from it.
Java Program
public class RemoveSpecialCharacters {
public static void main(String[] args) {
String str = "Hello@World#2024!";
StringBuilder result = new StringBuilder();
for (char c : str.toCharArray()) {
// Keep letters, digits, and whitespace; drop everything else
if (Character.isLetterOrDigit(c) || Character.isWhitespace(c)) {
result.append(c);
}
}
System.out.println(result.toString());
}
}Output
Core Logic
Keeping only characters that are letters, digits, or whitespace — and dropping everything else — filters out the special characters in one pass.
- 1A for-each loop visits each character of the string in turn.
- 2
Character.isLetterOrDigit(c)keeps ordinary letters and numbers. - 3
Character.isWhitespace(c)keeps spaces, tabs, and newlines. - 4A character passing either check is appended to a
StringBuilder; anything else — punctuation and symbols — is skipped entirely.
"Hello@World#2024!", the @, #, and ! characters are skipped, producing "HelloWorld2024".Key Point: This is the same 'everything left over' definition used to count special characters — here the special ones are dropped instead of tallied.
Why: Each character is checked once, and the result buffer grows to hold every letter, digit, and whitespace character kept.
Key Concepts
Approach 2: Regex Replace
public class RemoveSpecialCharactersRegex {
public static void main(String[] args) {
String str = "Hello@World#2024!";
// Removes anything that isn't a letter, digit, or whitespace
String result = str.replaceAll("[^a-zA-Z0-9\\s]", "");
System.out.println(result);
}
}
Output
Core Logic
A regex character class can express 'not a letter, digit, or whitespace' directly, removing every match in one call.
- 1
str.replaceAll("[^a-zA-Z0-9\\s]", "")matches any character that is NOT a letter, digit, or whitespace. - 2Every matched character is replaced with an empty string, which deletes it.
- 3What's left is a new string containing only letters, digits, and whitespace.
"Hello@World#2024!" removes @, #, and !, producing "HelloWorld2024".Key Point: The ^ at the start of the character class negates it — [^...] matches any character NOT listed, the opposite of a normal character class.
Why: replaceAll() still has to scan the whole string and build a new one holding every kept character.
Key Concepts
Approach 3: Java 8
import java.util.stream.Collectors;
public class RemoveSpecialCharactersStream {
public static void main(String[] args) {
String str = "Hello@World#2024!";
// Keeps letters, digits, and whitespace; drops everything else
String result = str.chars()
.filter(c -> Character.isLetterOrDigit(c) || Character.isWhitespace(c))
.mapToObj(c -> String.valueOf((char) c))
.collect(Collectors.joining());
System.out.println(result);
}
}
Output
Core Logic
The same 'letter, digit, or whitespace' check can filter a stream of character codes, then join what's left.
- 1
str.chars()returns anIntStreamof the string's character codes. - 2
.filter(c -> Character.isLetterOrDigit(c) || Character.isWhitespace(c))keeps only the characters that aren't special. - 3
.mapToObj(c -> String.valueOf((char) c))converts each surviving code back into a one-characterString. - 4
.collect(Collectors.joining())concatenates them all back into a single result string.
"Hello@World#2024!" drops @, #, and !, and joining what's left reassembles "HelloWorld2024".Key Point: The filter condition is the exact same boolean expression the loop version checks — streams just change how it's applied across the string.
Why: The stream still visits every character once, and Collectors.joining() builds a result string holding every kept character.