我正在创建一个应用程序,我将获取推文并将其存储在数据库中。我将有一个专栏的完整文本和另一个只有推文的文字将保留(我需要用词来计算以后最常用的词)。
我目前的工作方式是使用6种不同的.replaceAll()
函数,其中一些函数可能会被触发两次。例如,我将有一个for循环来删除每个"#标签"使用replaceAll()
。
问题在于我将编辑每隔几分钟就会发送的数千条推文,我认为我这样做的方式效率不会太高。
我对此顺序的要求是什么(也在下面的评论中写下):
以下是简短且可编辑的示例:
public class StringTest {
public static void main(String args[]) {
String text = "RT @AshStewart09: Vote for Lady Gaga for \"Best Fans\""
+ " at iHeart Awards\n"
+ "\n"
+ "RT!!\n"
+ "\n"
+ "My vote for #FanArmy goes to #LittleMonsters #iHeartAwards"
+ " htt…";
String[] hashtags = {"#FanArmy", "#LittleMonsters", "#iHeartAwards"};
System.out.println("Before: " + text + "\n");
// Delete all usernames mentioned (may run multiple times)
text = text.replaceAll("@AshStewart09", "");
System.out.println("First Phase: " + text + "\n");
// Delete all RT (retweets flags)
text = text.replaceAll("RT", "");
System.out.println("Second Phase: " + text + "\n");
// Delete all hashtags mentioned
for (String hashtag : hashtags) {
text = text.replaceAll(hashtag, "");
}
System.out.println("Third Phase: " + text + "\n");
// Replace all break lines with spaces
text = text.replaceAll("\n", " ");
System.out.println("Fourth Phase: " + text + "\n");
// Replace all double spaces with single spaces
text = text.replaceAll(" +", " ");
System.out.println("Fifth Phase: " + text + "\n");
// Delete all special characters except spaces
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();
System.out.println("Finaly: " + text);
}
}
答案 0 :(得分:3)
依赖replaceAll
可能是最大的性能杀手,因为它一次又一次地编译正则表达式。使用正则表达式可能是第二个最重要的问题。
假设所有用户名都以@
开头,我会替换
// Delete all usernames mentioned (may run multiple times)
text = text.replaceAll("@AshStewart09", "");
通过循环复制所有内容,直到找到@
,然后检查以下字符是否与列出的任何用户名匹配,并可能跳过它们。对于此查找,您可以使用trie。一个更简单的方法是使用replaceAll类似的正则表达式#\w+
循环以及HashMap
查找。
// Delete all RT (retweets flags)
text = text.replaceAll("RT", "");
在这里,
private static final Pattern RT_PATTERN = Pattern.compile("RT");
肯定会赢。可以类似地处理以下所有部件。而不是
// Delete all special characters except spaces
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();
你可以使用Guava的CharMatcher。方法removeFrom
完全按照您的方式执行,但collapseFrom
或trimAndCollapseFrom
可能会更好。
答案 1 :(得分:1)
根据现在关闭的question,这一切归结为
tweet = tweet.replaceAll("@\\w+|#\\w+|\\bRT\\b", "")
.replaceAll("\n", " ")
.replaceAll("[^\\p{L}\\p{N} ]+", " ")
.replaceAll(" +", " ")
.trim();
第二行似乎是多余的,因为第三行也会删除\n
。将第一行的替换更改为" "
不会更改允许聚合替换的结果。
tweet = tweet.replaceAll("@\\w*|#\\w*|\\bRT\\b|[^@#\\p{L}\\p{N} ]+", " ")
.replaceAll(" +", " ")
.trim();
我已将用户名和主题标签部分更改为仅使用#
或@
,因此不需要由特殊字符部分使用。这对于!@AshStewart09
等字符串的正确处理是必要的。
为了获得最佳性能,您肯定需要预编译模式。我还重新建议在第二部分使用Guava的CharMatcher
。番石榴是巨大的(我想2 MB),但你肯定会在那里找到更多有用的东西。所以最后你可以得到
private static final Pattern PATTERN =
Pattern.compile("@\\w*|#\\w*|\\bRT\\b|[^@#\\p{L}\\p{N} ]+");
private static final CharMatcher CHAR_MATCHER = CharMacher.is(" ");
tweet = PATTERN.matcher(tweet).replaceAll(" ");
tweet = CHAR_MATCHER.trimAndCollapseFrom(tweet, " ");
答案 2 :(得分:0)
你可以将所有被替换的东西内联到一个调用中,将所有被空格替换的东西替换为一个调用就像这样(也使用正则表达式来查找主题标签和用户名,因为这看起来更容易):
text = text.replaceAll("@\w+|#\w+|RT", "");
text = text.replaceAll("\n| +", " ");
text = text.replaceAll("[^a-zA-Z0-9 ]+", "").trim();