1

I want to do something like this: Replace all ck with k and all dd with wr and all f with m and 10 more replacements like this. I can do it with replace("ck","k").replace("dd","wr")and so on, but it seams silly and it is slow. Is there any function in java that does something like this? for example replace(string,stringArray1, stringArray2);

kkica
  • 4,034
  • 1
  • 20
  • 40
  • What's wrong with this approach? I think it's a lot easier to read than what you're proposing. – Joe C Sep 09 '17 at 17:55
  • this is an alternative: https://stackoverflow.com/a/1010945/3959856 – Jack Flamp Sep 09 '17 at 17:56
  • @JoeC perhaps, but it will iterate the string as many times as number of rules for replacement. – kkica Sep 09 '17 at 17:57
  • @JackFlamp Thanks, but that was not what i asked. Anyway, it had slipped my mind to use stringbuilders. – kkica Sep 09 '17 at 17:58
  • @JackFlamp StringBuilder doesnt seem to have the replace function, as described above. – kkica Sep 09 '17 at 18:03
  • 1
    Ok new try :) I am not sure about this one but here is another answer that might be interesting: https://stackoverflow.com/a/1326962/3959856 – Jack Flamp Sep 09 '17 at 18:04
  • 3
    ..or this kinda looks like your suggestion https://stackoverflow.com/a/13698843/3959856 – Jack Flamp Sep 09 '17 at 18:05

2 Answers2

2

Use an appendReplacement loop.

Here is a general purpose way to do it:

private static String replace(String input, Map<String, String> mappings) {
    StringBuffer buf = new StringBuffer();
    Matcher m = Pattern.compile(toRegex(mappings.keySet())).matcher(input);
    while (m.find())
        m.appendReplacement(buf, Matcher.quoteReplacement(mappings.get(m.group())));
    return m.appendTail(buf).toString();
}
private static String toRegex(Collection<String> keys) {
    return keys.stream().map(Pattern::quote).collect(Collectors.joining("|"));
}

If you're not using Java 8+, the second method would be:

private static String toRegex(Collection<String> keys) {
    StringBuilder regex = new StringBuilder();
    for (String key : keys) {
        if (regex.length() != 0)
            regex.append("|");
        regex.append(Pattern.quote(key));
    }
    return regex.toString();
}

Test code

Map<String, String> mappings = new HashMap<>();
mappings.put("ck","k");
mappings.put("dd","wr");
mappings.put("f", "m");
System.out.println(replace("odd flock", mappings)); // prints: owr mlok

See IDEONE for running version.

Andreas
  • 154,647
  • 11
  • 152
  • 247
1
Map<String, String> replacementMap = new HashMap<String, String>();
replacementMap.put("ck", "k");
replacementMap.put("dd", "wr");
replacementMap.put("f", "m");
// ...

String resultStr = "Abck fdddk wr fmck"; // whatever string to process
StringBuilder builder = new StringBuilder(resultStr); // wrap it in builder

Iterator<String> iterator = replacementMap.keySet().iterator();
while (iterator.hasNext()) {
    String strToReplace = iterator.next();
    replaceAll(builder, strToReplace, replacementMap.get(strToReplace));
}
System.out.println("Result is: " + builder.toString());

public static void replaceAll(StringBuilder builder, String from, String to) {
    int index = builder.indexOf(from);
    while (index != -1) {
        builder.replace(index, index + from.length(), to);
        index += to.length(); // Move to the end of the replacement
        index = builder.indexOf(from, index);
    }
}

The replaceAll() method was borrowed from this Jon Skeet's answer

Alternative to replaceAll() int his example is to use apache commons library, there is StrBuilder class which provides replaceAll() method. see this answer

Stasys Skliutas
  • 230
  • 1
  • 6