Java中最快的子字符串搜索方法是什么

2022-09-03 09:09:37

我需要实现一种使用Java在字符串列表(haystack)中搜索子字符串(针)的方法。

更具体地说,我的应用具有用户配置文件列表。如果我键入一些字母,例如“Ja”,然后搜索,那么名称中包含“ja”的所有用户都应该显示出来。例如,结果可能是“杰克”,“杰克逊”,“杰森”,“迪贾夫”。

在Java中,据我所知,有3个内置方法可以在字符串中查看搜索子字符串。

  1. string.contains()

  2. string.indexOf()

  3. 正则表达式。它类似于 string.matches(“ja”))

我的问题是:上述每种方法的运行时是什么?哪一个是检查字符串列表是否包含给定子字符串的最快,最有效或最流行的方法。

我知道有一些算法可以做同样的事情,比如Boyer-Moore字符串搜索算法,Knuth-Morris-Pratt算法等等。我不想使用它们,因为我只有一小串字符串,我认为现在使用它们对我来说有点过分了。此外,我必须为这种非内置算法键入大量额外的编码。如果您认为我的想法不正确,请随时纠正我。


答案 1

接受的答案不正确且不完整。

  • indexOf()使用不匹配的回溯执行朴素的字符串搜索。这在小图案/文本上非常快,但在大文本上显示的性能非常差
  • contains("ja")应该与 indexOf 相当(因为它委托给它)
  • matches("ja")不会提供正确的结果,因为它会搜索完全匹配(只有字符串才会完全匹配)"ja"
  • Pattern p = Pattern.compile("ja"); Matcher m = p.matcher("jack"); m.find();将是查找具有正则表达式的文本的正确方法。在实践中(使用大型文本),这将是仅使用java api的最有效方法。这是因为常量模式(如)不会由正则表达式引擎(速度较慢)处理,而是由Boyer-Moore算法(速度快)处理。"ja"

答案 2

就你问的三个而言,正则表达式会慢得多,因为当你有一个更简单的目标时,它需要把一个完整的状态机放在一起。对于 vs ...containsindexOf

2114 public boolean contains(CharSequence s) {
2115     return indexOf(s.toString()) > -1;
2116 }

(即,只是调用 ,但您可能会在每次调用时产生额外的创建。这只是 的一个实现,但是由于 的协定是 的简化,这可能是每个实现的工作方式。containsindexOfStringcontainscontainsindexOf