简体   繁体   中英

java String replace characters

I need your help for one tricky problem. I have one map like below

Map<Integer, String> ruleMap = new HashMap<>();
ruleMap.put(1, "A");
ruleMap.put(12, "Test - 12");
ruleMap.put(1012, "Test Metadata 12 A");

and I have one rule in which I am separating ids and collecting them into a list. By iterating over the list, I am replacing its ids by its respective value from map.

code :

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

List < String > idList = new ArrayList < > ();

Pattern p = Pattern.compile("[0-9]+");
Matcher m = p.matcher(rule);
while (m.find()) {
    idList.add(m.group());
}
for (String id: idList) {
    if (ObjectUtils.isNonEmpty(ruleMap.get(Integer.parseInt(id)))) {
        rule = rule.replaceFirst(id, ruleMap.get(Integer.parseInt(id)));
    }
}
System.out.println(rule);

I am getting output like this -

A AND Test - Test - 12 OR Test Metadata 12 A AND 12 or Test Metadata 12 A

as you can see for the first iteration of id 12 replaced its respected value but on the second occurrence of the id 1 2 replaced the value Test - 12 to Test - Test - 12 .

So can anyone help me with this?

You need to be doing regex replacement with proper word boundaries. I suggest using a regex iterator (as you were already doing), but use the pattern \\b\\d+\\b to match only full number strings. Then, at each match, do a lookup in the rule map, if the number be present, to find a replacement value. Use Matcher#appendReplacement to build out the replacement string as you go along.

Map<String, String> ruleMap = new HashMap<>();
ruleMap.put("1", "A");
ruleMap.put("12", "Test - 12");
ruleMap.put("1012", "Test Metadata 12 A");

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

Pattern pattern = Pattern.compile("\\b\\d+\\b");
Matcher m = pattern.matcher(rule);
StringBuffer buffer = new StringBuffer();
  
while(m.find()) {
    if (ruleMap.containsKey(m.group(0))) {
        m.appendReplacement(buffer, ruleMap.get(m.group(0)));
    }
}

m.appendTail(buffer);

System.out.println(rule + "\n" + buffer.toString());

This prints:

1 AND 12 OR 1012 AND 12 or 1012
A AND Test - 12 OR Test Metadata 12 A AND Test - 12 or Test Metadata 12 A

If you happen to use Java 9 or higher you could also use Matcher#replaceAll :

Map<Integer, String> ruleMap = new HashMap<>();
ruleMap.put(1, "A");
ruleMap.put(12, "Test - 12");
ruleMap.put(1012, "Test Metadata 12 A");

String rule = "1 AND 12 OR 1012 AND 12 or 1012";

rule = Pattern.compile("\\b\\d+\\b")
        .matcher(rule)
        .replaceAll(m -> ruleMap.getOrDefault(
                Integer.parseInt(m.group()), m.group()));

System.out.println(rule);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM