CharSequence (@NotNull CharSequence original, @NotNull Collection<@NotNull StringOperation> operations) { if (operations.isEmpty()) { return original; } final List<StringOperation> sorted = sort(operations); // The result looks like this: // originalChunk0 + replacement0 + ... + originalChunkN + replacementN + lastChunk final StringBuilder result = new StringBuilder(); int previousRangeEnd = 0; // each iteration appends original chunk and following replacement for (StringOperation operation : sorted) { TextRange range = operation.myRange; result.append(original, previousRangeEnd, range.getStartOffset()); result.append(operation.myReplacement); previousRangeEnd = range.getEndOffset(); // next original chunk starts where the current replacement ends } // last chunk result.append(original, previousRangeEnd, original.length()); return result.toString(); }