絮絮叨叨
记得在一年前就写过关于 String
类的源码解析的总结,在开始阅读 StrUtil
之前,我再次温习了一遍,感兴趣的朋友可以先阅读下找个感觉:
既然已经阅读过了 String
源码了,为什么还要阅读 StrUtil
源码呢? 在实际项目开发中 String
是我们最常使用的数据结构,这就导致我们对 String
的操作代码相当多,而这些操作又是独立于具体业务之外的通用代码,为了代码的简洁性、可读性,一般会把对 String
的各种操作封装成静态工具类,也就是本文的主角:StrUtil
,它几乎涵盖了所有你能想到或者想不到的字符串的通用操作方法。
源码初探
本文是对 StrUtil
源码解读的首篇总结,StrUtil
就是封装了对 String
操作的静态工具类,内部全是静态方法和静态常量:
可以看到作者在 StrUtil
中很贴心的预设了很多我们开发中几乎能想到的所有字符,比如空字符、空格、制表符等等。为了防止硬编码,我们可以直接通过该类去调用,而不是直接把符号硬编码在业务代码中。
简单花了个归类脑图(部分方法)总结下:
从方法脑图可以看出,每个方法基本都是见名知意的。
判空类方法
-
判断字符串是否为空白,空白的定义为:null、空白字符
public static boolean isBlank(CharSequence str) { //字符串长度 int length; //如果字符串为null 或者字符串长度等于0,直接返回 true if ((str == null) || ((length = str.length()) == 0)) { return true; } for (int i = 0; i < length; i++) { // 迭代检查字符串每个字符,只要有一个非空字符即为非空字符串 if (false == CharUtil.isBlankChar(str.charAt(i))) { return false; } } return true; }
-
如果对象是字符串,判断其是否为空白
public static boolean isBlankIfStr(Object obj) { //对象为null,直接返回 true if (null == obj) { return true; } else if (obj instanceof CharSequence) { //如果是字符串,调用 isBlank 方法进行判断 return isBlank((CharSequence) obj); } return false; }
-
判断字符串非空白
public static boolean isNotBlank(CharSequence str) { //isBlank 方法返回 false 即可 return false == isBlank(str); }
-
判断给定字符串数组中是否包含空白字符串,这里的参数为变成参数
hasBlank(CharSequence... strs)
public static boolean hasBlank(CharSequence... strs) { //如果数组为空,则返回true if (ArrayUtil.isEmpty(strs)) { return true; } //遍历检查数组中的字符串,只要满足一个为空白字符串,则返回true for (CharSequence str : strs) { if (isBlank(str)) { return true; } } //默认为false return false; }
-
判断给定的数组字符串是否全部为空白字符串
public static boolean isAllBlank(CharSequence... strs) { //如果数组为空,则返回true if (ArrayUtil.isEmpty(strs)) { return true; } //遍历检查数组中的字符串,只要满足一个不是空白字符串,则返回false for (CharSequence str : strs) { if (isNotBlank(str)) { return false; } } //默认返回true return true; }
-
判断字符串是否为空
public static boolean isEmpty(CharSequence str) { //字符串为null或者长度等于0 return str == null || str.length() == 0; }
-
如果对象是字符串,判断其是否为空
public static boolean isEmptyIfStr(Object obj) { //对象是null,返回true if (null == obj) { return true; } else if (obj instanceof CharSequence) { //对象是字符串,判断长度是否等于0 return 0 == ((CharSequence) obj).length(); } //默认false return false; }
-
判断字符串为非空
public static boolean isNotEmpty(CharSequence str) { //调用isEmpty方法满足false即可 return false == isEmpty(str); }
-
如果字符串为null ,返回默认值
public static String nullToDefault(CharSequence str, String defaultStr) { //就是一个简单的三目运算 return (str == null) ? defaultStr : str.toString(); }
-
如果字符串为空,返回默认值
public static String emptyToDefault(CharSequence str, String defaultStr) { //三目运算判断字符串是否为空 return isEmpty(str) ? defaultStr : str.toString(); }
-
如果字符串为空白字符串,返回默认值
public static String blankToDefault(CharSequence str, String defaultStr) { //三目运算判断字符串是否为空白字符串 return isBlank(str) ? defaultStr : str.toString(); }
-
判断指定字符串数组中是否包含空字符串
public static boolean hasEmpty(CharSequence... strs) { //数组为空,返回true if (ArrayUtil.isEmpty(strs)) { return true; } //遍历检查字符串数组中的字符串,其中一个为空,则为true for (CharSequence str : strs) { if (isEmpty(str)) { return true; } } //默认false return false; }
-
判断指定字符串数组中所有字符串是否都为空
public static boolean isAllEmpty(CharSequence... strs) { //数组为空,返回true if (ArrayUtil.isEmpty(strs)) { return true; } //遍历检查字符串数组中的字符串,其中一个不为空,则为false for (CharSequence str : strs) { if (isNotEmpty(str)) { return false; } } //默认true return true; }
-
判断指定字符串数组中所有字符串不为空
public static boolean isAllNotEmpty(CharSequence... args) { //只要调用 hasEmpty 检查数组中是否包含空字符串就行了 return false == hasEmpty(args); }
-
判断指定字符串数组中所有字符串不为空白字符
public static boolean isAllNotBlank(CharSequence... args) { //只要调用 hasBlank 检查数组中是否包含空字符串就行了 return false == hasBlank(args); }
去前后空格类方法
-
去除字符串前后空格
public static String trim(CharSequence str) { //三目运算判断字符串为null返回 null ,否则调用 trim(CharSequence str, int mode) 方法去除前后空格 return (null == str) ? null : trim(str, 0); }
-
去除给定字符串数组全部字符串前后空格
public static void trim(String[] strs) { //如果数组为null,不做任何处理 if (null == strs) { return; } //初始化动态字符串变量 String str; //迭代字符串数组 for (int i = 0; i < strs.length; i++) { //获取每个字符串 str = strs[i]; //字符串不为null,调用String的trim方法处理每个字符串,并重新赋值给当前数组指定索引处的字符串 if (null != str) { strs[i] = str.trim(); } } }
-
除去字符串头尾空格,如果字符串为null ,则返回空字符
public static String trimToEmpty(CharSequence str) { //字符串为null返回空字符串,否则调用 trim(str)方法去首尾空格 return str == null ? EMPTY : trim(str); }
-
除去字符串头尾空格,如果字符串为空字符,则返回 null
public static String trimToNull(CharSequence str) { //先调用 trim(str) 去除前后空格 final String trimStr = trim(str); //如果是空白字符则返回null,否则返回处理后的结果 return EMPTY.equals(trimStr) ? null : trimStr; }
-
除去字符串头部空格
public static String trimStart(CharSequence str) { // 调用 trim(CharSequence str, int mode) 方法处理,mode 参数传 -1 即可 return trim(str, -1); }
-
除去字符串尾部空格
public static String trimEnd(CharSequence str) { //调用 trim(CharSequence str, int mode) 方法处理,mode 参数传 1 即可 return trim(str, 1); }
-
除去字符串前后空格,可通过传参控制模式
/** * 除去字符串头尾部的空白符,如果字符串是<code>null</code>,依然返回<code>null</code>。 * * @param str 要处理的字符串 * @param mode <code>-1</code>表示trimStart,<code>0</code>表示trim全部, <code>1</code>表示trimEnd * @return 除去指定字符后的的字符串,如果原字串为<code>null</code>,则返回<code>null</code> */ public static String trim(CharSequence str, int mode) { //字符串为null,直接返回null if (str == null) { return null; } //字符串长度 int length = str.length(); //开始位置索引为0 int start = 0; //结束位置索引为字符串长度 int end = length; // 当 mode<=0 时,扫描字符串头部,确定开始裁剪的索引位置 if (mode <= 0) { //当 start < end 并且索引除的字符为空字符的时候,不停的向后迭代扫描,直到扫描到的字符不是空字符或者索引越界为止 while ((start < end) && (CharUtil.isBlankChar(str.charAt(start)))) { //不停的累加起始索引位置 start++; } } // 当 mode>=0 时, 扫描字符串尾部,确定结束裁剪的索引位置 if (mode >= 0) { // 当 start < end并且从字符串往后扫描到的字符为空字符时,不停的向前迭代扫描,直到扫描到的字符不是空字符或者扫描到字符串长度结束为止 while ((start < end) && (CharUtil.isBlankChar(str.charAt(end - 1)))) { //不停的递减结束索引位置 end--; } } //如果开始裁剪的所有位置大于0,或者 结束位置索引小于字符串长度,说明存在空白字符 if ((start > 0) || (end < length)) { //直接调用字符串的substring方法进行裁剪,即可移除前后空白字符 return str.toString().substring(start, end); } //字符串前后不存在空白字符串情况下,直接返回原字符串 return str.toString(); }
查找类方法
-
字符串是否以给定字符开始
public static boolean startWith(CharSequence str, char c) { //获取字符串第一个字符判断是否等于目标字符 return c == str.charAt(0); }
-
是否以指定字符串开头,可控制是否忽略大小写
public static boolean startWith(CharSequence str, CharSequence prefix, boolean isIgnoreCase) { //字符串为null 或者 待检测的开头字符串为null if (null == str || null == prefix) { //直接返回两个字符串是否都为null 就行,因为 null 肯定以null 开头啊,哈哈哈 return null == str && null == prefix; } //如果忽略大小写 if (isIgnoreCase) { //全部转为小写,再调用字符串的 startsWith 方法进行判断 return str.toString().toLowerCase().startsWith(prefix.toString().toLowerCase()); } else { //不忽略大小写,直接调用 startsWith 方法判断即可 return str.toString().startsWith(prefix.toString()); } }
-
是否以指定字符串开头,不忽略大小写
public static boolean startWith(CharSequence str, CharSequence prefix) { //直接调用 startWith(CharSequence str, CharSequence prefix, boolean isIgnoreCase) 方法,isIgnoreCase 传 false 即可 return startWith(str, prefix, false); }
-
是否以指定字符串开头,忽略大小写
public static boolean startWithIgnoreCase(CharSequence str, CharSequence prefix) { //直接调用 startWith(CharSequence str, CharSequence prefix, boolean isIgnoreCase) 方法,isIgnoreCase 传 true 即可 return startWith(str, prefix, true); }
-
给定字符串是否以字符串数组中的任意一个字符串开头
public static boolean startWithAny(CharSequence str, CharSequence... prefixes) { //字符串为空 或者 数组为空,直接返回false if (isEmpty(str) || ArrayUtil.isEmpty(prefixes)) { return false; } //遍历检查字符串是否以数组中任意一个字符串开头,并且不忽略大小写 for (CharSequence suffix : prefixes) { //只要查找到一个成立,直接返回 true if (startWith(str, suffix, false)) { return true; } } //找不到则默认返回false return false; }
-
是否以给定的字符结尾
public static boolean endWith(CharSequence str, char c) { //获取字符串最后一个字符,判断是否与给定字符相等就行了 return c == str.charAt(str.length() - 1); }
-
是否以给定字符串结尾,可控制是否忽略大小写
public static boolean endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase) { //待检查字符串等于null 或者 前缀字符串等于null if (null == str || null == suffix) { //只要其中一个等于null ,直接判断两个都等于null ,就成立了,毕竟 null 肯定以null 结尾嘛 return null == str && null == suffix; } //如果忽略大小写 if (isIgnoreCase) { //先转为小写,再调用字符串的 endsWith 方法判断即可 return str.toString().toLowerCase().endsWith(suffix.toString().toLowerCase()); } else { //不忽略大小写,直接调用字符串的 endsWith 方法判断即可 return str.toString().endsWith(suffix.toString()); } }
-
是否以指定字符串结尾,不忽略大小写
public static boolean endWith(CharSequence str, CharSequence suffix) { //直接调用 endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase),isIgnoreCase传 false 即可 return endWith(str, suffix, false); }
-
是否以指定字符串结尾,忽略大小写
public static boolean endWithIgnoreCase(CharSequence str, CharSequence suffix) { //直接调用 endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase),isIgnoreCase传 true 即可 return endWith(str, suffix, true); }
-
给定字符串是否以字符串数组中任意一个字符串结尾
public static boolean endWithAny(CharSequence str, CharSequence... suffixes) { //字符串为空 或者数组为空,直接返回false if (isEmpty(str) || ArrayUtil.isEmpty(suffixes)) { return false; } //遍历字符串数组,检查给定字符串中是否以该字符串结尾,不忽略大小写 for (CharSequence suffix : suffixes) { //一旦找到一个成立的字符串,直接返回true if (endWith(str, suffix, false)) { return true; } } //没找到,默认返回false return false; }
-
指定字符是否在字符串中出现过
public static boolean contains(CharSequence str, char searchChar) { //直接调用 indexOf 方法获取字符索引位置,大于 -1 表示存在 return indexOf(str, searchChar) > -1; }
-
指定字符串是否在字符串中出现过
public static boolean contains(CharSequence str, CharSequence searchStr) { //字符串等于null或者被查找的字符串等于null 直接返回false if (null == str || null == searchStr) { return false; } //调用字符串的 contains 方法判断是否存在查找的字符串 return str.toString().contains(searchStr); }
-
查找指定字符串是否包含指定字符串列表中的任意一个字符串
public static boolean containsAny(CharSequence str, CharSequence... testStrs) { //直接调用 getContainsStr 获取字符串数组中存在的字符串,不为null表示存在 return null != getContainsStr(str, testStrs); }
-
查找指定字符串是否包含指定字符列表中的任意一个字符
public static boolean containsAny(CharSequence str, char... testChars) { //字符串不为空进行处理 if (false == isEmpty(str)) { //字符串长度 int len = str.length(); //遍历字符串字符,查找包含字符列表中是否包含该字符 for (int i = 0; i < len; i++) { //检查到一个直接返回true if (ArrayUtil.contains(testChars, str.charAt(i))) { return true; } } } //默认返回false return false; }
-
检查指定字符串中是否只包含给定的字符
public static boolean containsOnly(CharSequence str, char... testChars) { //字符串不为空进行处理 if (false == isEmpty(str)) { //字符串长度 int len = str.length(); //遍历字符串字符,查找字符串中的字符是否在字符列表中 for (int i = 0; i < len; i++) { //检查到一个不存在直接返回false if (false == ArrayUtil.contains(testChars, str.charAt(i))) { return false; } } } //默认返回true return true; }
-
给定字符串是否包含空白字符
public static boolean containsBlank(CharSequence str) { //字符串等于null,直接返回false if (null == str) { return false; } //字符串长度 final int length = str.length(); //字符串长度等于0,返回false if (0 == length) { return false; } //遍历检查字符串中字符是否存在空字符 for (int i = 0; i < length; i += 1) { //检查到一个空字符,直接返回true if (CharUtil.isBlankChar(str.charAt(i))) { return true; } } //默认false return false; }
-
查找指定字符串是否包含指定字符串列表中的任意一个字符串,包含则返回第一个字符串
public static String getContainsStr(CharSequence str, CharSequence... testStrs) { //指定字符串为空 或者字符串列表为空,直接返回null if (isEmpty(str) || ArrayUtil.isEmpty(testStrs)) { return null; } //遍历字符串列表,检查是否在指定字符串中 for (CharSequence checkStr : testStrs) { //检查到在指定的字符串中,直接返回该字符串 if (str.toString().contains(checkStr)) { return checkStr.toString(); } } //获取不到则默认返回null return null; }
-
是否包含给定字符串,忽略大小写
public static boolean containsIgnoreCase(CharSequence str, CharSequence testStr) { if (null == str) { // 如果被监测字符串和 return null == testStr; } //先转换为小写再调用 contains 方法判断 return str.toString().toLowerCase().contains(testStr.toString().toLowerCase()); }
-
查找指定字符串是否包含指定字符串列表中的任意一个字符串,忽略大小写
public static boolean containsAnyIgnoreCase(CharSequence str, CharSequence... testStrs) { //调用getContainsStrIgnoreCase查找包含的第一个字符串,不为null表示存在 return null != getContainsStrIgnoreCase(str, testStrs); }
-
查找指定字符串是否包含指定字符串列表中的任意一个字符串,存在则返回第一个字符串,忽略大小写
public static String getContainsStrIgnoreCase(CharSequence str, CharSequence... testStrs) { //字符串为空 或者字符串列表为空,直接返回null if (isEmpty(str) || ArrayUtil.isEmpty(testStrs)) { return null; } //遍历查找字符串列表中是都存在字符串,包含在指定的字符串中,并忽略大小写 for (CharSequence testStr : testStrs) { //检查到一个存在,直接返回该字符串 if (containsIgnoreCase(str, testStr)) { return testStr.toString(); } } //找不到则默认返回null return null; }
最后
StrUtil
包含太多静态方法了,开篇先记录这些方法,后续待更新.....
推荐阅读
参考:
Hutool
官网:hutool.cn/github
:github.com/looly/hutoo…
更多原创文章会在公众号第一时间推送,欢迎扫码关注 张少林同学