内容简介:判断一个字符串是否包含某个特定子串是常见的场景,比如判断一篇文章是否包含敏感词汇、判断日志是否有在最直观判断的方法是
1 简介
判断一个字符串是否包含某个特定子串是常见的场景,比如判断一篇文章是否包含敏感词汇、判断日志是否有 ERROR 信息等。本文将介绍四种方法并进行性能测试。
2 四种方法
2.1 JDK原生方法String.indexOf
在 String 的函数中,提供了 indexOf(subStr) 方法,返回子串 subStr 第一次出现的位置,如果不存在则返回-1。例子如下:
//包含Java
assertEquals(7, "Pkslow Java".indexOf("Java"));
//如果包含多个,返回第一次出现位置
assertEquals(0, "Java Java".indexOf("Java"));
//大小写敏感
assertEquals(-1, "Google Guava".indexOf("guava"));
2.2 JDK原生方法String.contains
最直观判断的方法是 contains(subStr) ,返回类型为 boolean ,如果包含返回 true ,不包含则返回 false 。例子如下:
//包含Java
assertTrue("code in Java".contains("Java"));
//大小写敏感,不包含GO
assertFalse("Let's go".contains("GO"));
//转为大写后包含
assertTrue("Let's go".toUpperCase().contains("GO"));
实际上, String 的 contains 方法是通过调用 indexOf 方法来判断的,源码如下:
public boolean contains(CharSequence s) {
return indexOf(s.toString()) > -1;
}
2.3 JDK原生正则匹配Pattern
通过强大的正则匹配来判断,虽然有点杀鸡用牛刀的感觉,但也不是不能用,例子如下:
Pattern pattern = Pattern.compile("Java");
//包含Java
Matcher matcher1 = pattern.matcher("Python, Java, Go, C++");
assertTrue(matcher1.find());
//不包含Java
Matcher matcher2 = pattern.matcher("Python, C, Go, Matlab");
assertFalse(matcher2.find());
2.4 Apache库StringUtils.contains
Apache的 commons-lang3 提供许多开箱即用的功能, StringUtils 就提供了许多与字符串相关的功能,例子如下:
//包含sub
assertTrue(StringUtils.contains("String subString", "sub"));
//大小写敏感
assertFalse(StringUtils.contains("This is Java", "java"));
//忽略大小写
assertTrue(StringUtils.containsIgnoreCase("This is Java", "java"));
3 性能对比
我们使用 JMH 工具来对四种方法进行性能测试, Maven 引入代码如下:
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${openjdk.jmh.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${openjdk.jmh.version}</version>
</dependency>
测试代码如下:
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class StringContainsPerformanceTest {
@State(Scope.Thread)
public static class MyState {
private String text = "If you want to be smart; read. If you want to be really smart; read a lot.";
Pattern pattern = Pattern.compile("read");
}
@Benchmark
public int indexOf(MyState state) {
return state.text.indexOf("read");
}
@Benchmark
public boolean contains(MyState state) {
return state.text.contains("read");
}
@Benchmark
public boolean stringUtils(MyState state) {
return StringUtils.contains(state.text, "read");
}
@Benchmark
public boolean pattern(MyState state) {
return state.pattern.matcher(state.text).find();
}
public static void main(String[] args) throws Exception {
Options options = new OptionsBuilder()
.include(StringContainsPerformanceTest.class.getSimpleName())
.threads(6)
.forks(1)
.warmupIterations(3)
.measurementIterations(6)
.shouldFailOnError(true)
.shouldDoGC(true)
.build();
new Runner(options).run();
}
}
测试结果如下:
Benchmark Mode Cnt Score Error Units contains avgt 6 11.331 ± 1.435 ns/op indexOf avgt 6 11.250 ± 1.822 ns/op pattern avgt 6 101.196 ± 12.047 ns/op stringUtils avgt 6 29.046 ± 3.873 ns/op
最快的就是 indexOf 方法,其次是 contains 方法,二者应该没有实际区别, contains 是调用 indexOf 来实现的。Apache的 StringUtils 为第三方库,相对慢一些。最慢的是使用了正则的 Pattern 的方法,这不难理解,正则引擎的匹配是比较耗性能的。
4 总结
本文介绍了判断一个字符串是否包含某个特定子串的四种方法,并通过性能测试进行了对比。其中性能最好的是String的 indexOf 方法和 contains 方法,建议使用 contains 方法,性能好,跟 indexOf 相比,更直观,更不容易犯错。毕竟让每个人时刻记住返回 -1 代表不存在也不是一件容易的事。
但是,使用 indexOf 和 contains 方法都需要注意做判空处理,这时 StringUtils 的优势就体现出来了。
欢迎关注公众号< 南瓜慢说 >,将持续为你更新...
多读书,多分享;多写作,多整理。
以上所述就是小编给大家介绍的《【Java必修课】判断String是否包含子串的四种方法及性能对比》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 算法面试必修课:动态规划基础题型归纳(一)
- PyFlink漫谈|PyFlink必修课!一小时吃透PyFlink
- 前端必修课:ES2017+下的构建工具原理与实战
- 营销者的必修课:区分“人工智能”和“计算机视觉”
- [译] 真·程序员必修书单
- AI产品经理必修:揭开算法的面纱(动态规划)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。