< prev index next >

src/java.base/share/classes/java/lang/String.java

Print this page
rev 12026 : [mq]: 8058779-Faster-implementation-of-String-replace-MIDDLE

@@ -38,10 +38,11 @@
 import java.util.StringJoiner;
 import java.util.function.IntConsumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 import java.util.stream.StreamSupport;
 
 /**
  * The {@code String} class represents character strings. All

@@ -2245,12 +2246,55 @@
      * @param  replacement The replacement sequence of char values
      * @return  The resulting string
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
-                this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
+        String starget = target.toString();
+        int targLen = starget.length();
+        String srepl = replacement.toString();
+
+        // special case: replacing empty substrings
+        if (targLen == 0) {
+            return splitAndJoin(srepl);
+        }
+
+        int i = indexOf(starget);
+        // special case: nothing to replace
+        if (i < 0) {
+            return this;
+        }
+
+        StringJoiner joiner = new StringJoiner(replacement);
+        joiner.add(substring(0, i));
+        i += targLen;
+        int j;
+        while ((j = indexOf(starget, i)) > 0) {
+            joiner.add(substring(i, j));
+            i = j + targLen;
+        }
+        return joiner.add(substring(i)).toString();
+    }
+
+    /**
+     * Returns this string with every empty substring
+     * replaced by the given delimiter.
+     * If this string is empty, the delimiter is returned.
+     * If the delimiter is empty, unchanged this string
+     * is returned.
+     */
+    private String splitAndJoin(String delimiter) {
+        if (isEmpty()) {
+            return delimiter;
+        }
+        if (delimiter.isEmpty()) {
+            return this;
+        }
+        return chars()
+                .mapToObj(i -> String.valueOf((char)i))
+                .collect(Collectors.joining(delimiter,
+                                            delimiter,
+                                            delimiter));
     }
 
     /**
      * Splits this string around matches of the given
      * <a href="../util/regex/Pattern.html#sum">regular expression</a>.
< prev index next >