如何忽略大小写使用String.contains()?有无更优替代方案?
忽略大小写的字符串包含比较优化方案
嘿,这个问题我之前也碰到过!你现在用的s1.toLowerCase().contains(s2.toLowerCase())其实完全没问题,代码简洁还好懂,但既然你关心String不可变带来的临时对象创建问题,或者想找更优雅的替代方案,我给你几个实用的选择:
用JDK原生方法
regionMatches手动封装
这个方法是JDK自带的,支持忽略大小写的区域匹配,而且不需要把整个字符串转成小写,只在匹配时逐段比较,对于长字符串来说性能更优。你可以自己封装一个工具方法:public static boolean containsIgnoreCase(String target, String searchStr) { // 边界处理:空字符串默认视为包含 if (searchStr.isEmpty()) { return true; } int searchLen = searchStr.length(); int targetLen = target.length(); // 遍历目标字符串的所有可能起始位置 for (int i = 0; i <= targetLen - searchLen; i++) { // regionMatches参数:是否忽略大小写,目标字符串起始索引,搜索字符串,搜索字符串起始索引,匹配长度 if (target.regionMatches(true, i, searchStr, 0, searchLen)) { return true; } } return false; }这个方法不会生成完整的小写副本,只在需要比较的字符段做大小写转换,内存和性能都更友好。
借助Apache Commons Lang工具类
如果你的项目已经引入了Apache Commons Lang依赖(很多Java项目都会用这个工具包),直接用现成的StringUtils.containsIgnoreCase就好,它内部已经处理了所有边界情况(比如null值、空字符串),不用自己造轮子:import org.apache.commons.lang3.StringUtils; // 直接调用一行搞定 boolean isContained = StringUtils.containsIgnoreCase(s1, s2);这个方法的实现也很高效,而且经过了大量场景的验证,非常靠谱。
Java 8+ Stream实现(仅作思路参考)
还有一种用Stream的写法,但我个人不推荐在实际项目里用——因为代码繁琐,性能也不如上面两种方案,不过可以作为拓展思路看看:public static boolean containsIgnoreCaseWithStream(String target, String searchStr) { if (searchStr.length() > target.length()) { return false; } return IntStream.range(0, target.length() - searchStr.length() + 1) .anyMatch(startIdx -> IntStream.range(0, searchStr.length()) .allMatch(charIdx -> Character.toLowerCase(target.charAt(startIdx + charIdx)) == Character.toLowerCase(searchStr.charAt(charIdx)))); }
最后补充一句:其实你最初的双转小写方案在绝大多数业务场景下都完全够用,代码可读性拉满,只有当你处理超长篇字符串,或者对性能有极致要求时,才需要考虑替换成上面的优化方案。
内容的提问来源于stack exchange,提问作者Java Developer
相关产品推荐
相关产品推荐

