内容简介:判断一个字符串是否包含某个特定子串是常见的场景,比如判断一篇文章是否包含敏感词汇、判断日志是否有在最直观判断的方法是
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产品经理必修:揭开算法的面纱(动态规划)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。