Java中字符串搜索的4种方法性能比较

检查字符串是否包含子字符串的几种方法,并将比较每种方法的性能。

1、String.indexOf
indexOf 方法返回子字符串第一次出现的位置索引,如果没有找到则返回 -1。

String mainString = "Hello, World!";
String subString = "Hello";

if (mainString.indexOf(subString) != -1) {
    System.out.println("字符串包含子字符串");
}

2、使用 contains 方法:
String 类中提供了 contains 方法,用于检查一个字符串是否包含指定的子字符串。

String mainString = "Hello, World!";
String subString = "Hello";

if (mainString.contains(subString)) {
    System.out.println("字符串包含子字符串");
}

3、使用正则表达式:
Java 中也可以使用正则表达式来检查字符串是否包含特定的子字符串。

import java.util.regex.Pattern;
import java.util.regex.Matcher;

String mainString = "Hello, World!";
String subString = "Hello";

Pattern pattern = Pattern.compile(subString);
Matcher matcher = pattern.matcher(mainString);

if (matcher.find()) {
    System.out.println("字符串包含子字符串");
}

4、StringUtils.containsIgnoreCase
使用Apache Commons Lang库中的StringUtils# containsIgnoreCase:

Assert.assertTrue(StringUtils.containsIgnoreCase("Runaway train", "train"));
Assert.assertTrue(StringUtils.containsIgnoreCase("Runaway train", "Train"));

我们可以看到它将检查字符串中是否包含子字符串,而忽略大小写。这就是为什么当我们搜索“Trai”以及“Runaway Train”中的“trai”时containsIgnoreCase返回true 。

此方法不会像以前的方法那样有效,因为它需要额外的时间来忽略该情况。containsIgnoreCase在内部将每个字母转换为大写,并比较转换后的字母而不是原始字母。

性能比较
我们将使用名为Java Microbenchmark Harness (JMH)的开源微基准框架来确定哪种方法在执行时间方面最有效。

结果:

  • contains: 14.736 ns
  • indexOf: 14.200 ns
  • containsStringUtilsIgnoreCase: 385.632 ns
  • 模式匹配: 1014.633 ns

indexOf 方法的效率最高,其次是 contains 方法。因为 contains 在内部使用 indexOf,所以耗时较长。

containsStringUtilsIgnoreCase 与前几种方法相比耗时更长,因为它不区分大小写。

searchWithPattern 的平均耗时甚至比上一个更长,这证明使用模式是这项任务最糟糕的选择。

补充:ArrayUtils
来自同一个commons-lang库的另一个类ArrayUtils

boolean compareWithMultipleStringsUsingArrayUtils(String str, String ... strs) {
    return ArrayUtils.contains(strs, str);
}

ArrayUtils是一个实用程序类,有助于检查对象数组中是否存在某个元素。因此,我们利用它来帮助我们实现涉及String 的用例。不幸的是, ArrayUtils没有提供任何以不区分大小写的方式查找String对象的方法。

使用ArrayUtils()与多个字符串进行比较性能与StringUtils 类似、