1

我有一堆字符串,其中包含一些应该用图像替换的特定标记。所以起初我用标记和图像创建了哈希图:

Map<String, String> images = new HashMap<String, String>();
images.put(":img:howdy:", "path/images/hello.png");
images.put(":img:code:", "path/images/code.png");
images.put(":img:smile:", "path/images/sm.png");
//...and 70 more records

字符串看起来像:

这是一个字符串 :img:howdy:,你知道的 :img:smile:

甚至更多:img:smile:

这是一个带有图像的字符串:img:code::img:smile:

解析后,所有标记都计划用图像替换。

我坚持以下几点:

Map<String, String> images = new HashMap<String, String>();
images.put(":img:howdy:", "path/images/hello.png");
images.put(":img:code:", "path/images/code.png");
images.put(":img:smile:", "path/images/sm.png");

String[] strings = {"This is a string :img:howdy:, you know it :img:smile:",
                 "And even more:img:smile:",
                 "This is a string with images:img:code::img:smile:"};

for (String text : images.keySet()) {
    for (String string : strings) {
        if(string.contains(text)) {
            string.replace(text, images.get(text));
        }
    }
}

首先,标记被替换,但有很多迭代。其次,如果我使用,例如,StringBuilder,我有很多重复,一些标记被替换,一些没有。

我不擅长字符串解析和相应的算法(目前),所以在查看我选择的方法后不要向我扔石头。

按照 Dariusz Waver 的建议,添加 了一些 Reworked,这就是我所拥有的:

private final String IMAGE_PATTERN = ":s:\\w+:";

//.......

Pattern p = Pattern.compile(IMAGE_PATTERN);
Matcher m = p.matcher(message);
while(m.find())
{
    String imgPattern = message.substring(m.start(), m.end());
    String imgPath = ImgPaths.images.get(imgPattern);
    
    //If there's no such image in Images Map
    if(imgPattern != null) {
        message = message.replace(imgPattern, imgPath);
        m.reset(message);
    }
}

StringBuilder result = new StringBuilder();
result.append(timestamp).append(" - ").append(sender)
        .append(": ").append(message);

考虑到文本量非常大,有什么方法可以使其更加优化?

4

4 回答 4

1

string是内部 for 循环的局部变量。string.replace()创建一个新字符串,并且不更改当前字符串。但即使string = string.replace(...)在这里也无济于事,因为重新分配它不会改变数组的内容。

您必须将内部for 循环替换为:

for (int i = 0; i < strings.length; i++) {
    if(strings[i].contains(text)) { // this check is not really necessary
        strings[i] = strings[i].replace(text, images.get(text));
    }
}
于 2013-02-18T10:15:27.047 回答
1

我建议反过来做:首先找到所有出现的 regex :\w+:\w+,然后在地图中搜索它的值,然后,如果找到,替换字符串。

对于大量的图像和大量的文本,这将是更好的方法。

但是,您的代码非常干净,如果您没有任何性能问题,您可以保持原样 - 前提是您确实完成了 jlordo 发布的修复:

for (int i = 0; i < strings.length; i++) {
    if(strings[i].contains(text)) {
        strings[i] = strings[i].replace(text, images.get(text));
    }
}
于 2013-02-18T10:16:02.983 回答
1

你为什么不试试像这样的模板库:StringTemplate

示例代码:

String[] strings = {"This is a string <howdy>, you know it <smile>",
                     "And even more <smile>",
                     "This is a string with images <code><smile>"};

for (String string : strings) {
    ST hello = new ST(string);

    hello.add("howdy", "path/images/hello.png");
    hello.add("code", "path/images/code.png");
    hello.add("smile", "path/images/sm.png");

    System.out.println(hello.render());
}

为什么要重新发明轮子?

于 2013-02-18T10:44:32.423 回答
0

1-.contains似乎没有必要

2-字符串是不可变的,你必须做String string = string.replaceAll(...)

于 2013-02-18T10:17:23.477 回答