Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Map replaceAll与多个字符串匹配_Java_Regex_String_Replace - Fatal编程技术网

Java Map replaceAll与多个字符串匹配

Java Map replaceAll与多个字符串匹配,java,regex,string,replace,Java,Regex,String,Replace,我有下面的程序,我想用对应的值替换所有出现的字符串,其中一个单词作为键存在于映射中 我已经实现了4种方法。它们各自执行大致相同的功能,但方式不同。前3个的输出不正确,因为下一次更换会覆盖上一次更换的结果。第四个有效,但这只是因为我正在替换整个字符串中的单个字符。这是非常低效的,因为我只检查整个字符串的一个子字符串 是否有一种方法可以安全地替换所有事件,而不覆盖以前的替换 我注意到Apache有一个StringUtils.replaceach()方法,但我更喜欢使用map 输出: Apple BA

我有下面的程序,我想用对应的值替换所有出现的字符串,其中一个单词作为键存在于映射中

我已经实现了4种方法。它们各自执行大致相同的功能,但方式不同。前3个的输出不正确,因为下一次更换会覆盖上一次更换的结果。第四个有效,但这只是因为我正在替换整个字符串中的单个字符。这是非常低效的,因为我只检查整个字符串的一个子字符串

是否有一种方法可以安全地替换所有事件,而不覆盖以前的替换

我注意到Apache有一个
StringUtils.replaceach()
方法,但我更喜欢使用map

输出:

Apple BApplenApplenApple CApplentApplelope DApplete Apple BApplenApplenApple CApplentApplelope DApplete
Apple BApplenApplenApple CApplentApplelope DApplete Apple BApplenApplenApple CApplentApplelope DApplete
Apple BApplenApplenApple CApplentApplelope DApplete Apple BApplenApplenApple CApplentApplelope DApplete
Apple Banana Cantalope Date Apple Banana Cantalope Date
ReplaceMap.java

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReplaceMap {
    private static Map<String, String> replacements;

    static {
        replacements = new HashMap<String, String>();
        replacements.put("a", "Apple");
        replacements.put("b", "Banana");
        replacements.put("c", "Cantalope");
        replacements.put("d", "Date");
    }

    public ReplaceMap() {
        String phrase = "a b c d a b c d";

        System.out.println(mapReplaceAll1(phrase, replacements));
        System.out.println(mapReplaceAll2(phrase, replacements));
        System.out.println(mapReplaceAll3(phrase, replacements));
        System.out.println(mapReplaceAll4(phrase, replacements));
    }

    public String mapReplaceAll1(String str, Map<String, String> replacements) {
        for (Map.Entry<String, String> entry : replacements.entrySet()) {
            str = str.replaceAll(entry.getKey(), entry.getValue());
        }

        return str;
    }

    public String mapReplaceAll2(String str, Map<String, String> replacements) {
        for (String key : replacements.keySet()) {
            str = str.replaceAll(Pattern.quote(key),
                    Matcher.quoteReplacement(replacements.get(key)));
        }

        return str;
    }

    public String mapReplaceAll3(String str, Map<String, String> replacements) {        
        String regex = new StringBuilder("(")
            .append(join(replacements.keySet(), "|")).append(")").toString();
        Matcher matcher = Pattern.compile(regex).matcher(str);

        while (matcher.find()) {
            str = str.replaceAll(Pattern.quote(matcher.group(1)),
                    Matcher.quoteReplacement(replacements.get(matcher.group(1))));
        }

        return str;
    }

    public String mapReplaceAll4(String str, Map<String, String> replacements) {        
        StringBuilder buffer = new StringBuilder();
        String regex = new StringBuilder("(")
            .append(join(replacements.keySet(), "|")).append(")").toString();
        Pattern pattern = Pattern.compile(regex);

        for (int i = 0, j = 1; i < str.length(); i++, j++) {
            String s = str.substring(i, j);
            Matcher matcher = pattern.matcher(s);


            if (matcher.find()) {
                buffer.append(s.replaceAll(Pattern.quote(matcher.group(1)),
                            Matcher.quoteReplacement(replacements.get(matcher.group(1)))));
            } else {
                buffer.append(s);
            }
        }


        return buffer.toString();
    }

    public static String join(Collection<String> s, String delimiter) {
        StringBuilder buffer = new StringBuilder();
        Iterator<String> iter = s.iterator();
        while (iter.hasNext()) {
            buffer.append(iter.next());
            if (iter.hasNext()) {
                buffer.append(delimiter);
            }
        }
        return buffer.toString();
    }

    public static void main(String[] args) {
        new ReplaceMap();
    }
}
import java.util.Collection;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.Map;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
公共类替换映射{
私有静态地图替换;
静止的{
replacements=newhashmap();
替换。放置(“a”、“苹果”);
替换。放置(“b”、“香蕉”);
替换品。放置(“c”、“哈密瓜”);
替换。将(“日期”);
}
公共地图(){
字符串短语=“a b c d a b c d”;
System.out.println(mapReplaceAll1(短语,替换));
System.out.println(mapReplaceAll2(短语,替换));
System.out.println(mapReplaceAll3(短语,替换));
System.out.println(mapReplaceAll4(短语,替换));
}
公共字符串mapReplaceAll1(字符串str,映射替换){
对于(Map.Entry:replacements.entrySet()){
str=str.replaceAll(entry.getKey(),entry.getValue());
}
返回str;
}
公共字符串mapReplaceAll2(字符串str,映射替换){
for(字符串键:replacements.keySet()){
str=str.replaceAll(模式.引号(键),
Matcher.quoteReplacement(replacements.get(key));
}
返回str;
}
公共字符串mapReplaceAll3(字符串str,映射替换){
字符串正则表达式=新的StringBuilder(“”)
.append(join(replacements.keySet(),“|”)append(”).toString();
Matcher Matcher=Pattern.compile(regex).Matcher(str);
while(matcher.find()){
str=str.replaceAll(Pattern.quote(matcher.group(1)),
Matcher.quoteReplacement(replacements.get(Matcher.group(1));
}
返回str;
}
公共字符串mapReplaceAll4(字符串str,映射替换){
StringBuilder缓冲区=新的StringBuilder();
字符串正则表达式=新的StringBuilder(“”)
.append(join(replacements.keySet(),“|”)append(”).toString();
Pattern=Pattern.compile(regex);
对于(inti=0,j=1;i
我的方法如下。可能有更快的解决方案,但如果你喜欢这个想法,你可以更进一步

public String mapReplaceAll5(String str, Map<String, String> replacements) {
    Map<String, String> origToMarker = new HashMap<String, String>();
    Map<String, String> markerToRepl = new HashMap<String, String>();
    char c = 32000;
    for(Entry<String, String> e : replacements.entrySet()) {
        origToMarker.put(e.getKey(), String.valueOf(c));
        markerToRepl.put(String.valueOf(c--), e.getValue());
    }
    for (Map.Entry<String, String> entry : origToMarker.entrySet()) {
        str = str.replaceAll(entry.getKey(), entry.getValue());
    }
    for (Map.Entry<String, String> entry : markerToRepl.entrySet()) {
        str = str.replaceAll(entry.getKey(), entry.getValue());
    }

    return str;
}
公共字符串mapReplaceAll5(字符串str,映射替换){
Map origToMarker=newhashmap();
Map markerToRepl=new HashMap();
字符c=32000;
对于(条目e:replacements.entrySet()){
origToMarker.put(e.getKey(),String.valueOf(c));
markerToRepl.put(String.valueOf(c--),e.getValue());
}
对于(Map.Entry:origToMarker.entrySet()){
str=str.replaceAll(entry.getKey(),entry.getValue());
}
for(Map.Entry:markerToRepl.entrySet()){
str=str.replaceAll(entry.getKey(),entry.getValue());
}
返回str;
}
我会这样做:

replace(str, map)
    if we have the empty string, the result is the empty string.
    if the string starts with one of the keys from the map:
        the result is the replacement associated with that key + replace(str', map)
             where str' is the substring of str after the key
    otherwise the result is the first character of str + replace(str', map)
             where str' is the substring of str without the first character
注意,尽管它是递归的,但它可以(而且应该,由于Java臭名昭著的小堆栈空间)实现为循环,并将结果的第一部分(即替换字符串或第一个字符)写入stringbuilder

如果地图中有一个键是某个其他键(即“键”、“键”)的前缀,则可能需要尝试缩短键的长度

进一步注意,可以设计一种更快的算法,使用trys而不是hasmap。这也是解决关键问题模棱两可的办法

以下是一个大纲(未经测试):

publicstaticstringreplace(stringit,Map){
StringBuilder sb=新的StringBuilder();
List keys=map.keySet();//TODO:按长度递减排序!!
下一步:while(it.length()>0){
用于(字符串k:键){
如果(从(k)开始){
//我们有一场比赛!
sb.append(map.get(k));
it=it.substring(k.length(),it.length());
继续下一步;
}
}
//不匹配,前进一个字符
某人附加(它是字符(0));
it=it.substring(1,it.length());
}
使某人返回字符串();
}

您可以使用
StringUtils.replaceach
与地图一起使用,但代价是将数据复制到一对arr中
public static String replace(String it, Map<String, String> map) {
    StringBuilder sb = new StringBuilder();
    List<String> keys = map.keySet();      // TODO: sort by decreasing length!!
    next: while (it.length() > 0) {
        for (String k : keys) {
            if (it.startsWith(k)) {
                // we have a match!
                sb.append(map.get(k));
                it = it.substring(k.length(), it.length());
                continue next;
            }
        }
        // no match, advance one character
        sb.append(it.charAt(0));
        it = it.substring(1, it.length());
    }
    return sb.toString();
}
public String replaceEach(String s, Map<String, String> replacements)
{
    int size = replacements.size();
    String[] keys = replacements.keySet().toArray(new String[size]);
    String[] values = replacements.values().toArray(new String[size]);
    return StringUtils.replaceEach(s, keys, values);
}