代码之家  ›  专栏  ›  技术社区  ›  Martlark

用java替换字符串中所有标记的最佳方法

  •  2
  • Martlark  · 技术社区  · 17 年前

    我有一个服务方法,它接受一个String,然后用标签库中的项目替换String中的标签。具体如下:

    for( MetaDataDTO tag : tagValues )
    {
        message = message.replace( tag.getKey(), tag.getText1() );
    }
    

    显然;这会产生大量新字符串,这很糟糕。但是StringBuilder替换方法对于一个字符串中的多个字符串来说很麻烦。我该如何提高我的方法的效率?

    2 回复  |  直到 17 年前
        1
  •  10
  •   cletus    17 年前

    基本上,你想复制执行 Matcher.replaceAll()

    public static String replaceTags(String message, Map<String, String> tags) {
      Pattern p = Pattern.compile("#(\\w+)#");
      Matcher m = p.matcher(message);
      boolean result = m.find();
      if (result) {
        StringBuffer sb = new StringBuffer();
        do {
          m.appendReplacement(sb, tags.containsKey(m.group(1) ? tags.get(m.group(1)) : "");
          result = m.find();
        } while (result);
        m.appendTail(sb);
        message = sb.toString();
      }
      return message;
    }
    

    注: 我对有效标签(即正则表达式中的\w)做出了假设。你需要满足真正有效的要求(例如“#([\w]+)#”)。

    Map<String, String> tags = new HashMap<String, String>();
    tags.add("firstName", "Skippy");
    

    tags.add("#firstName#", "Skippy");
    

    如果第二个是正确的,你需要相应地调整。

    此方法在消息字符串中只进行一次传递,因此没有比这更有效的方法了。

        2
  •  0
  •   Martlark    17 年前

    谢谢你们的帮助。当然,我学到了更多关于java的知识。这是我的解决方案。通过这种方式可以支持不同外观的标签和标签内的标签:

    private static String replaceAllTags(String message, Map< String, String > tags)
    {
        StringBuilder sb = new StringBuilder( message );
        boolean tagFound = false;
        /**
         * prevent endless circular text replacement loops
         */
        long recurrancyChecker = 5000;
    
        do
        {
            tagFound = false;
            Iterator it = tags.entrySet().iterator();
            while( it.hasNext() )
            {
                Map.Entry pairs = (Map.Entry) it.next();
    
                int start = sb.indexOf( pairs.getKey().toString() );
    
                while( start > -1 && --recurrancyChecker > 0 )
                {
                    int length = pairs.getKey().toString().length();
                    sb.replace( start, start + length, pairs.getValue().toString() );
                    start = sb.indexOf( pairs.getKey().toString() );
                    tagFound = true;
                }
            }
        }
        while( tagFound && --recurrancyChecker > 0 );
        return sb.toString();
    }