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"));

实际上,Stringcontains方法是通过调用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代表不存在也不是一件容易的事。

但是,使用indexOfcontains方法都需要注意做判空处理,这时StringUtils的优势就体现出来了。


欢迎关注公众号<南瓜慢说>,将持续为你更新...

多读书,多分享;多写作,多整理。

最新文章

  1. sharepoint 开发相关工具总结
  2. Java程序设计的DOS命令基础
  3. 【OpenWRT】 Chaos Calmer 15.05 编译
  4. NopCommerce中的单例
  5. HBase 专题技术收录
  6. struts2访问servlet API
  7. php插入转义与查找转义
  8. 【python】字符排序
  9. Raft论文学习笔记
  10. Spring系列之手写一个SpringMVC
  11. Http 状态码:
  12. 添加PROPAGATION_REQUIRES_NEW 事务没有产生作用
  13. Spring如何支持可扩展
  14. w7安装双系统
  15. [leetcode]50. Pow(x, n)求幂
  16. W5100S芯片特性
  17. 1024 Palindromic Number int_string转换 大整数相加
  18. 自己写的JdbcUtils小工具-----得到Connection对象
  19. 读DataSnap源代码(一)
  20. 清理MVC4 Internaet 项目模板清理

热门文章

  1. The sequence and de novo assembly of the giant panda genome.ppt
  2. 基于STC89C516的多游戏实现
  3. 86)PHP,PDO常用函数
  4. java开发环境搭建(jdk安装)和经常出现问题的探讨
  5. rocket mq 入门文档
  6. SQL提高性能
  7. unittest(23)- python发邮件
  8. Hibernate之cascade属性和inverse属性
  9. 学习HEXO的历程
  10. (转)linux如何获取鼠标相对位置信息