Skip to content

Improve performance of StringUtils.replaceEach. - #7494

Merged
alextwoods merged 2 commits into
masterfrom
alexwoo/linear-replace-each
Oct 29, 2026
Merged

alextwoods merged 2 commits into
masterfrom
alexwoo/linear-replace-each

Conversation

@alextwoods

Copy link
Copy Markdown
Contributor

Motivation

Improves the performance of StringUtils.replaceEach (used in query parameter, path segement and XML escaping), making it linear.

Changes

  1. Remember the next match position of each search string and search for it again only after a replacement has moved past the remembered match.
  2. Copy unmatched text between replacements with one bulk append instead of one character at a time.
  3. Return the text unchanged when the search list or the replacement list is null (fixes an existing mismatch between javadoc and behavior)

Compatibility

  1. There is no known compatibility risk. The public API is unchanged and the output is the same as before for every input, including overlapping matches, ties, empty search strings and null replacements.

Testing

New unit tests cover the documented examples, null and empty arguments, the length mismatch exception, overlapping and tied matches, and matches consumed by an earlier replacement. One test runs 20,000 random small inputs through the new code and a copy of the old algorithm and checks that the outputs are equal. Another test replaces 100,000 & characters followed by a < and checks the result. I ran these tests against the old code, and the large-input timing checks failed there.

License

  • I confirm that this pull request can be released under the Apache 2 license

## Motivation

Improves the performance of `StringUtils.replaceEach` (used in query parameter, path segement and XML escaping), making it linear. 

## Changes

1. Remember the next match position of each search string and search for it again only after a replacement has moved past the remembered match.
2. Copy unmatched text between replacements with one bulk append instead of one character at a time.
3. Return the text unchanged when the search list or the replacement list is null.
4. Add a changelog entry for the bugfix.

## Compatibility

1. There is no known compatibility risk. The public API is unchanged and the output is the same as before for every input, including overlapping matches, ties, empty search strings and null replacements.

## Testing

New unit tests cover the documented examples, null and empty arguments, the length mismatch exception, overlapping and tied matches, and matches consumed by an earlier replacement. One test runs 20,000 random small inputs through the new code and a copy of the old algorithm and checks that the outputs are equal. Another test replaces 100,000 `&` characters followed by a `<` and checks the result. I ran these tests against the old code, and the large-input timing checks failed there.
@alextwoods alextwoods added the perf-improvement Label for PRs that contain performance improvement changes. label Oct 28, 2026
@alextwoods
alextwoods requested a review from a team as a code owner October 28, 2026 19:16
@alextwoods
alextwoods requested review from ianbotsf and kdaily October 28, 2026 19:43
@alextwoods alextwoods added the no-api-surface-area-change Indicate there is no API surface area change and thus API surface area review is not required label Oct 28, 2026
@alextwoods
alextwoods added this pull request to the merge queue Oct 29, 2026
Merged via the queue into master with commit ea090f3 Oct 29, 2026
14 checks passed
@alextwoods
alextwoods deleted the alexwoo/linear-replace-each branch October 29, 2026 15:47
@github-actions

Copy link
Copy Markdown

This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Oct 29, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

no-api-surface-area-change Indicate there is no API surface area change and thus API surface area review is not required perf-improvement Label for PRs that contain performance improvement changes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants