In Java, what is the difference between String.replaceAll and String.replaceFirst, and how do they differ from String.replace?
answer
- replaceAll/replaceFirst = regex; replace = literal
- All return a NEW string (immutable)
- First arg is a pattern, replacement arg is ALSO special ($, \)
- replaceFirst stops after one match
- replace(".",..) is safe; replaceAll(".",..) matches everything
basics
~10 sreplaceAll changes every match of a regex; replaceFirst changes only the first match. Both treat their first argument as a regular expression. String.replace is different: it works on plain literal text, not regex.
solid answer
~40 sAll three return a new String (Strings are immutable). replaceAll(regex, repl) replaces every substring matching the regex; replaceFirst(regex, repl) replaces only the first match. The first argument of both is compiled as a regular expression, so characters like . [ ] ( ) * + ? | \ are special. Crucially, the replacement string is also interpreted: $1 is a group back-reference and a backslash escapes, so a literal $ or \ in the replacement must be escaped or run through Matcher.quoteReplacement. By contrast, String.replace(CharSequence, CharSequence) takes literal text on both sides, no regex and no replacement metacharacters, so it is the right choice when you just want to swap one fixed substring for another.
go deeper
Knows replaceAll changes all matches, replaceFirst only the first, and that both return a new string.
Explains that the first argument is a regex (so . [ ] etc. are special) and that String.replace is the literal alternative.
Also flags the replacement-string trap ($/) and the per-call compilation cost, recommending Pattern.compile for hot paths.
Frames API choice as a correctness-and-performance decision, sets team conventions (literal replace by default, quoteReplacement for user data), and reasons about immutability/GC pressure at scale.
## What these methods do Java's `String` class has several substitution methods. Two of them are **regex-based** and one is **literal**. - A **regular expression (regex)** is a small pattern language for describing sets of strings. For example the pattern `\d+` means "one or more digits". In a regex, certain characters are *metacharacters* with special meaning: `. ^ $ * + ? ( ) [ ] { } | \`. - A **literal** string is taken character-for-character with no special meaning. ### `replaceAll(String regex, String replacement)` Compiles `regex` as a pattern, scans the whole string, and replaces **every** non-overlapping match with `replacement`. Returns a brand-new `String` (the original is never mutated, because Java strings are immutable). ### `replaceFirst(String regex, String replacement)` Same as `replaceAll` but stops after the **first** match. ### `replace(CharSequence target, CharSequence replacement)` This one is **not** regex. Both arguments are literal text. It replaces every occurrence of the literal `target`. There is also `replace(char, char)`. ## The two traps **Trap 1 — the pattern argument is a regex.** `"a.b.c".replaceAll(".", "-")` does NOT replace dots; `.` means "any character", so you get all dashes. To replace literal dots use `replaceAll("\\.", "-")` (the `\\.` is the Java source for the two-character regex `\.`) or, simpler, `replace(".", "-")`. **Trap 2 — the replacement argument is also special.** In the *replacement* string of `replaceAll`/`replaceFirst`, `$` introduces a group reference (`$1`, `$2`, …) and `\` is an escape. So `replaceAll("x", "$5")` throws because there is no group 5, and inserting a literal `$` requires `\$` or `Matcher.quoteReplacement("$")`. ## When to use which - Fixed substring swap, performance-sensitive, no pattern needed → **`replace`** (no regex compilation, no surprises). - Pattern-based, change all → **`replaceAll`**. - Pattern-based, change only the first → **`replaceFirst`**. ## Cost note `replaceAll`/`replaceFirst` compile the regex on every call. In a hot loop, precompile once with `Pattern.compile(...)` and reuse `matcher.replaceAll(...)`.
- Why does "1.2.3".replaceAll(".", ",") produce all commas instead of "1,2,3"?Because . in regex means 'any character', so every character matches and is replaced. Use replaceAll("\\.", ",") or replace(".", ",").
- If you call replaceAll thousands of times with the same pattern, what's the optimization?Precompile with Pattern.compile once and reuse its Matcher.replaceAll, avoiding recompiling the regex on every call.
saying these in an interview costs you the question
- Thinking String.replace uses regex (it does not)
- Assuming replaceAll's pattern argument is literal text
- Forgetting the methods return a new string and trying to mutate in place
- Not knowing $ and \ are special in the replacement string too