一种高效通用的字符串前置匹配方法

现状

一般情况下,我们使用字符串的前置匹配方法,如果要做的通用一些,忽略大小写,可能会这么写:

复制

从功能上说,这么写当然没问题。但是,我们忽略了一个问题:toLowerCase(toUpperCase) 方法是耗时的。为什么耗时?以 toLowerCase 为例:

复制

会遍历字符串并且重新赋值给 newString,最终调用的是 Character.toLowerCase 方法:

复制

最后这里的 toLowerCaseImpl 就是真正实现的方法,这是一个 Native 方法,也是由 C/C++ 完成的。

toLowerCaseImpl 效率高,然而在调用 toLowerCaseImpl 之前的操作,会耗时。那我们最开始的 startsWithIgnoreCase 方法的性能瓶颈就在这里了。如果想要减少耗时,应该怎么办呢?

分析

耗时关键点:toLowerCase。这个方法,当然是没什么替代的空间, 只能另辟蹊径。关于 String 的忽略大小写比对,除了 toLowerCase 和 toUpperCase 之后再比对,我们还会想到一个方法:equalsIgnoreCase。

这个方法的效率会比先 toLowerCase 之后再比对的效率高。为什么呢?

复制

并不会对字符串进行全拷贝,foldCase 就直接调用到上文中 Character.toLowerCase 方法,最后调用到 toLowerCaseImpl 方法。

实现

说了这么多,肯定有小伙伴会问:我们不是在聊字符串前置匹配吗?equals 速度快了和前置匹配有什么关系呢?

让我们想想前置匹配的逻辑:处理好忽略大小写后的字符串,进行 startsWith 操作,是不是可以等同于,字符串 str 截取从下标为 0 到 prefix.length 的位置,这部分前置字符串再和 prefix 进行 equalsIgnoreCase?如果 str 的长度小于等于 prefix 的长度,其实 startsWith 和 equals 是一样的。

逻辑已经梳理清楚了,那么就简单了,动手写一下新的忽略字符串大小写的前置匹配通用方法:

复制

方法写好了,让我们写个 Demo 验证一下是否真的有优化效果吧。

验证

上 Demo 代码:

复制

这里的 startsWithIgnoreCaseNew 方法就是新实现的 startsWithIgnoreCase 方法。当 str 和 prefix 完全一样的时候,验证结果如下:

如果在 str 和 prefix 中随机加一些大写字符,验证结果如下:

高下立判!

高下立判!

高下立判!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180720G0U22C00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券