使用Regex而不是String中的contains()进行缓慢渲染

时间:2018-03-28 13:37:36

标签: java regex string

我有一个代码块,其中包含很多条件中包含“contains()”的条件。我正在尝试使用正则表达式这么容易,但渲染时需要花费很多时间(SocketTimeoutException)。

旧代码:

if (!url.toLowerCase().contains("wikipedia")
                            && !URL.toLowerCase().contains("vikidia")
                            && !URL.toLowerCase().contains("wikimini")
                            && !URL.toLowerCase().contains("dictionnaire")
                            && !URL.toLowerCase().contains("dictionary")
                            && !URL.toLowerCase().contains("traduction")
                            && !URL.toLowerCase().contains("wiktionary")
                            && !URL.toLowerCase().contains("academia.edu")
                            && !URL.toLowerCase().contains("about.me")
                            && !URL.toLowerCase().contains("facebook")
                            && !URL.toLowerCase().contains("linkedin")
                            && !URL.toLowerCase().contains("viadeo")
                            && !URL.toLowerCase().contains("flickr")
                            && !URL.toLowerCase().contains("google+")
                            && !URL.toLowerCase().contains("plus.google")
                            && !URL.toLowerCase().contains("instagram")
                            && !URL.toLowerCase().contains("linkedin")
                            && !URL.toLowerCase().contains("netlog")
                            && !URL.toLowerCase().contains("orkut")
                            && !URL.toLowerCase().contains("pinterest")
                            && !URL.toLowerCase().contains("twitter")
                            && !URL.toLowerCase().contains("tripadvisor")
                            && !URL.toLowerCase().contains("youtube")
                            && !URL.toLowerCase().contains("vimeo")
                            && !URL.toLowerCase().contains("dailymotion")
                            && !URL.toLowerCase().contains("pagesjaunes")
                            && !URL.toLowerCase().contains("indeed")
                            && !URL.toLowerCase().contains("jobteaser.com")
                            && !URL.toLowerCase().contains("mappy.com")
                            && !URL.toLowerCase().contains("slideshare")
                            && !URL.toLowerCase().contains("meteofrance.com")
                            && !URL.toLowerCase().contains("linternaute.com")
                            && !URL.toLowerCase().contains("news.google")
                            && !URL.toLowerCase().contains("persee.fr") // portail de revues en sciences humaines et sociales
                            && !URL.toLowerCase().contains("/downloads") // the url for downloading 
                            && !URL.toLowerCase().contains("/streaming")
                            && !URL.toLowerCase().contains("http://stackoverflow.com/")
                            && !URL.endsWith("pdf")
                            && !URL.endsWith("txt")
                            && !URL.endsWith("ps")
                            && !URL.endsWith("dwf")
                            && !URL.endsWith("klm")
                            && !URL.endsWith("kmz")
                            && !URL.endsWith("xls")
                            && !URL.endsWith("xlsx")
                            && !URL.endsWith("ppt")
                            && !URL.endsWith("pptx")
                            && !URL.endsWith("doc")
                            && !URL.endsWith("docx")
                            && !URL.endsWith("rtf")
                            && !URL.endsWith("swf")
                            && !URL.contains(".en.")
                            && !URL.contains("/en/")
                            && !URL.contains("/en.")
                            && !URL.contains("books.")
                            && !URL.contains("forum.")
                            && !URL.contains("forum")
                            && !URL.contains("blog.")
                            && !URL.contains("infogreffe.fr/") //to test
                            && !URL.contains("bing.com/images")) {

                        if (!URL.matches(".*\\btraduction\\b.*")) {
...
                    }

反应一:

if (!URL.toLowerCase().matches("^.*(wikipedia|vikidia|wikimini|dictionnaire|dictionary|traduction|wiktionary|(academia.edu)|(about.me)|facebook|linkedin|viadeo|flickr|(google+)|instagram|(plus.google)|linkedin|netlog|orkut|pinterest|twitter|tripadvisor|youtube|(vimeo+)|dailymotion|pagesjaunes|indeed|(jobteaser.com)|(mappy.com)|slideshare|(meteofrance.com)|(linternaute.com)|(news.google)|(persee.fr)|(/downloads)|(/streaming)|(stackoverflow.com)|pdf|txt|ps|dwf|klm||xls|xlsx|ppt|pptx|doc|docx|rtf|swf|(.en.)|(/en/)|(books.)|(forum.)|(blog.)|(infogreffe.fr/)|(bing.com/images)).*$")
                            ) {...}

你有没有更好的想法重构旧的。非常感谢你

3 个答案:

答案 0 :(得分:1)

我可以提出一个建议,至少可以帮助部分解决有关URL结尾的逻辑。您可以将URL的结尾提取为字符串。然后,创建一个包含列入黑名单的字符串的地图,如下所示:

String URLend = "some_value";
Map<String, Integer> map = new HashMap<>();
map.put("pdf", 1);
map.put("txt", 1);
map.put("ps", 1);
map.put("dwf", 1);
// and other terms...

现在,您可以轻松检查网址末尾是否与列入黑名单的字词匹配:

if (map.get(URLend) != null) {
    // then the URL is blacklisted
}

这里的优点是查找时间是恒定的,比冗长的正则表达式快得多。缺点是这只会覆盖你需要比较的整个字符串的逻辑,这不能完全解决你的问题。

答案 1 :(得分:0)

首先,基于正则表达式的解决方案很慢的最可能原因是您使用.*matches。问题是*是贪婪的,所以它会尝试匹配尽可能多的字符。这意味着在找到匹配项之前会有很多回溯跟踪。在模式不匹配的情况下甚至更多的回溯。

使用Matcher::find可能会获得更好的性能,并摆脱.*子模式。

通过分解String::contains调用,您在使用toLowerCase的代码中也可以获得更好的性能。当然代码会更具可读性。

但如果您真的担心性能问题,我认为您应该研究像Rabin-Karp algorithm这样的快速字符串搜索算法。 (处理&#34;以&#34结尾;单独搜索。)

答案 2 :(得分:0)

您可以将“contains”和“endsWith”测试组合成一个正则表达式。
如果匹配,则测试失败。

只需要一点点重构,而且速度非常快。

(?i)(?:^.*(d(?:ocx?|wf)|k(?:lm|mz)|p(?:df|ptx?|s)|(?:rt|sw)f|txt|xlsx?)\s*$|(\.en\.|/(?:downloads|en[./]|streaming)|a(?:bout\.me|cademia\.edu)|b(?:ing\.com/images|(?:log|ooks)\.)|d(?:ailymotion|iction(?:ary|naire))|f(?:acebook|lickr|orum\.?)|google\+|http://stackoverflow\.com/|in(?:deed|fogreffe\.fr/|stagram)|(?:jobteaser|m(?:appy|eteofrance))\.com|lin(?:kedin|ternaute\.com)|ne(?:tlog|ws\.google)|orkut|p(?:agesjaunes|ersee\.fr|interest|lus\.google)|(?:slideshar|youtub)e|t(?:r(?:aduction|ipadvisor)|witter)|vi(?:(?:ad|m)eo|kidia)|wik(?:imini|tionary)))

https://regex101.com/r/7sS4ek/1

 (?i)
 (?:
    # endsWith
    ^ 
    .* 
    (                             # (1 start)
       d
       (?: ocx? | wf )
     | k
       (?: lm | mz )
     | p
       (?: df | ptx? | s )
     | (?: rt | sw )
       f
     | txt
     | xlsx?
    )                             # (1 end)
    \s* 
    $ 
  | 
    # contains
    (                             # (2 start)
       \. en \. 
     | /
       (?: downloads | en [./] | streaming )
     | a
       (?: bout \. me | cademia \. edu )
     | b
       (?:
          ing \. com/images
        | (?: log | ooks )
          \. 
       )
     | d
       (?:
          ailymotion
        | iction
          (?: ary | naire )
       )
     | f
       (?: acebook | lickr | orum \.? )
     | google \+ 
     | http://stackoverflow \. com/
     | in
       (?: deed | fogreffe \. fr/ | stagram )
     | (?:
          jobteaser
        | m
          (?: appy | eteofrance )
       )
       \. com
     | lin
       (?: kedin | ternaute \. com )
     | ne
       (?: tlog | ws \. google )
     | orkut
     | p
       (?:
          agesjaunes
        | ersee \. fr
        | interest
        | lus \. google
       )
     | (?: slideshar | youtub )
       e
     | t
       (?:
          r
          (?: aduction | ipadvisor )
        | witter
       )
     | vi
       (?:
          (?: ad | m )
          eo
        | kidia
       )
     | wik
       (?: imini | tionary )
    )                             # (2 end)
 )