字符串是否为空白,空白的定义如下:
+ *例:
+ *注意:该方法与 {@link #isEmpty(CharSequence)} 的区别是: + * 该方法会校验空白字符,且性能相对于 {@link #isEmpty(CharSequence)} 略慢。
+ *建议:
+ *字符串是否为非空白,非空白的定义如下:
+ *例:
+ *注意:该方法与 {@link #isNotEmpty(CharSequence)} 的区别是: + * 该方法会校验空白字符,且性能相对于 {@link #isNotEmpty(CharSequence)} 略慢。
+ *建议:仅对于客户端(或第三方接口)传入的参数使用该方法。
+ * + * @param str 被检测的字符串 + * @return 是否为非空 + * @see #isBlank(CharSequence) + */ + public static boolean isNotBlank(CharSequence str) { + return false == isBlank(str); + } + + /** + *指定字符串数组中,是否包含空字符串。
+ *如果指定的字符串数组的长度为 0,或者其中的任意一个元素是空字符串,则返回 true。
+ *例:
+ *注意:该方法与 {@link #isAllBlank(CharSequence...)} 的区别在于:
+ *指定字符串数组中的元素,是否全部为空字符串。
+ *如果指定的字符串数组的长度为 0,或者所有元素都是空字符串,则返回 true。
+ *例:
+ *注意:该方法与 {@link #hasBlank(CharSequence...)} 的区别在于:
+ *字符串是否为空,空的定义如下:
+ *例:
+ *注意:该方法与 {@link #isBlank(CharSequence)} 的区别是:该方法不校验空白字符。
+ *建议:
+ *字符串是否为非空白,非空白的定义如下:
+ *例:
+ *注意:该方法与 {@link #isNotBlank(CharSequence)} 的区别是:该方法不校验空白字符。
+ *建议:该方法建议用于工具类或任何可以预期的方法参数的校验中。
+ * + * @param str 被检测的字符串 + * @return 是否为非空 + * @see #isEmpty(CharSequence) + */ + public static boolean isNotEmpty(CharSequence str) { + return false == isEmpty(str); + } + + /** + * 当给定字符串为null时,转换为Empty + * + * @param str 被检查的字符串 + * @return 原字符串或者空串 + * @see #nullToEmpty(CharSequence) + * @since 4.6.3 + */ + public static String emptyIfNull(CharSequence str) { + return nullToEmpty(str); + } + + /** + * 当给定字符串为null时,转换为Empty + * + * @param str 被转换的字符串 + * @return 转换后的字符串 + */ + public static String nullToEmpty(CharSequence str) { + return nullToDefault(str, EMPTY); + } + + /** + * 如果字符串是 {@code null},则返回指定默认字符串,否则返回字符串本身。 + * + *+ * nullToDefault(null, "default") = "default" + * nullToDefault("", "default") = "" + * nullToDefault(" ", "default") = " " + * nullToDefault("bat", "default") = "bat" + *+ * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * @return 字符串本身或指定的默认字符串 + */ + public static String nullToDefault(CharSequence str, String defaultStr) { + return (str == null) ? defaultStr : str.toString(); + } + + /** + * 如果字符串是{@code null}或者"",则返回指定默认字符串,否则返回字符串本身。 + * + *
+ * emptyToDefault(null, "default") = "default" + * emptyToDefault("", "default") = "default" + * emptyToDefault(" ", "default") = " " + * emptyToDefault("bat", "default") = "bat" + *+ * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * @return 字符串本身或指定的默认字符串 + * @since 4.1.0 + */ + public static String emptyToDefault(CharSequence str, String defaultStr) { + return isEmpty(str) ? defaultStr : str.toString(); + } + + /** + * 如果字符串是{@code null}或者""或者空白,则返回指定默认字符串,否则返回字符串本身。 + * + *
+ * emptyToDefault(null, "default") = "default" + * emptyToDefault("", "default") = "default" + * emptyToDefault(" ", "default") = "default" + * emptyToDefault("bat", "default") = "bat" + *+ * + * @param str 要转换的字符串 + * @param defaultStr 默认字符串 + * @return 字符串本身或指定的默认字符串 + * @since 4.1.0 + */ + public static String blankToDefault(CharSequence str, String defaultStr) { + return isBlank(str) ? defaultStr : str.toString(); + } + + /** + * 当给定字符串为空字符串时,转换为{@code null} + * + * @param str 被转换的字符串 + * @return 转换后的字符串 + */ + public static String emptyToNull(CharSequence str) { + return isEmpty(str) ? null : str.toString(); + } + + /** + *
是否包含空字符串。
+ *如果指定的字符串数组的长度为 0,或者其中的任意一个元素是空字符串,则返回 true。
+ *例:
+ *注意:该方法与 {@link #isAllEmpty(CharSequence...)} 的区别在于:
+ *指定字符串数组中的元素,是否全部为空字符串。
+ *如果指定的字符串数组的长度为 0,或者所有元素都是空字符串,则返回 true。
+ *例:
+ *注意:该方法与 {@link #hasEmpty(CharSequence...)} 的区别在于:
+ *指定字符串数组中的元素,是否都不为空字符串。
+ *如果指定的字符串数组的长度不为 0,或者所有元素都不是空字符串,则返回 true。
+ *例:
+ *注意:该方法与 {@link #isAllEmpty(CharSequence...)} 的区别在于:
+ *+ * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *
+ * trim(null) = null + * trim("") = "" + * trim(" ") = "" + * trim("abc") = "abc" + * trim(" abc ") = "abc" + *+ * + * @param str 要处理的字符串 + * @return 除去头尾空白的字符串,如果原字串为{@code null},则返回{@code null} + */ + public static String trim(CharSequence str) { + return (null == str) ? null : trim(str, 0); + } + + /** + * 除去字符串头尾部的空白,如果字符串是{@code null},返回{@code ""}。 + * + *
+ * StrUtil.trimToEmpty(null) = "" + * StrUtil.trimToEmpty("") = "" + * StrUtil.trimToEmpty(" ") = "" + * StrUtil.trimToEmpty("abc") = "abc" + * StrUtil.trimToEmpty(" abc ") = "abc" + *+ * + * @param str 字符串 + * @return 去除两边空白符后的字符串, 如果为null返回"" + * @since 3.1.1 + */ + public static String trimToEmpty(CharSequence str) { + return str == null ? EMPTY : trim(str); + } + + /** + * 除去字符串头尾部的空白,如果字符串是{@code null}或者"",返回{@code null}。 + * + *
+ * StrUtil.trimToNull(null) = null + * StrUtil.trimToNull("") = null + * StrUtil.trimToNull(" ") = null + * StrUtil.trimToNull("abc") = "abc" + * StrUtil.trimToEmpty(" abc ") = "abc" + *+ * + * @param str 字符串 + * @return 去除两边空白符后的字符串, 如果为空返回null + * @since 3.2.1 + */ + public static String trimToNull(CharSequence str) { + final String trimStr = trim(str); + return EMPTY.equals(trimStr) ? null : trimStr; + } + + /** + * 除去字符串头部的空白,如果字符串是{@code null},则返回{@code null}。 + * + *
+ * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *
+ * trimStart(null) = null + * trimStart("") = "" + * trimStart("abc") = "abc" + * trimStart(" abc") = "abc" + * trimStart("abc ") = "abc " + * trimStart(" abc ") = "abc " + *+ * + * @param str 要处理的字符串 + * @return 除去空白的字符串,如果原字串为{@code null}或结果字符串为{@code ""},则返回 {@code null} + */ + public static String trimStart(CharSequence str) { + return trim(str, -1); + } + + /** + * 除去字符串尾部的空白,如果字符串是{@code null},则返回{@code null}。 + * + *
+ * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 + * + *
+ * trimEnd(null) = null + * trimEnd("") = "" + * trimEnd("abc") = "abc" + * trimEnd(" abc") = " abc" + * trimEnd("abc ") = "abc" + * trimEnd(" abc ") = " abc" + *+ * + * @param str 要处理的字符串 + * @return 除去空白的字符串,如果原字串为{@code null}或结果字符串为{@code ""},则返回 {@code null} + */ + public static String trimEnd(CharSequence str) { + return trim(str, 1); + } + + /** + * 除去字符串头尾部的空白符,如果字符串是{@code null},依然返回{@code null}。 + * + * @param str 要处理的字符串 + * @param mode {@code -1}表示trimStart,{@code 0}表示trim全部, {@code 1}表示trimEnd + * @return 除去指定字符后的的字符串,如果原字串为{@code null},则返回{@code null} + */ + public static String trim(CharSequence str, int mode) { + String result; + if (str == null) { + result = null; + } else { + int length = str.length(); + int start = 0; + int end = length;// 扫描字符串头部 + if (mode <= 0) { + while ((start < end) && (CharUtil.isBlankChar(str.charAt(start)))) { + start++; + } + }// 扫描字符串尾部 + if (mode >= 0) { + while ((start < end) && (CharUtil.isBlankChar(str.charAt(end - 1)))) { + end--; + } + } + if ((start > 0) || (end < length)) { + result = str.toString().substring(start, end); + } else { + result = str.toString(); + } + } + + return result; + } + + // ------------------------------------------------------------------------ startWith + + /** + * 字符串是否以给定字符开始 + * + * @param str 字符串 + * @param c 字符 + * @return 是否开始 + */ + public static boolean startWith(CharSequence str, char c) { + if (isEmpty(str)) { + return false; + } + return c == str.charAt(0); + } + + /** + * 是否以指定字符串开头
+ * StrUtil.indexOfIgnoreCase(null, *, *) = -1 + * StrUtil.indexOfIgnoreCase(*, null, *) = -1 + * StrUtil.indexOfIgnoreCase("", "", 0) = 0 + * StrUtil.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 + * StrUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 + * StrUtil.indexOfIgnoreCase("aabaabaa", "", 2) = 2 + * StrUtil.indexOfIgnoreCase("abc", "", 9) = -1 + *+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @return 位置 + * @since 3.2.1 + */ + public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { + return indexOfIgnoreCase(str, searchStr, 0); + } + + /** + * 指定范围内查找字符串 + * + *
+ * StrUtil.indexOfIgnoreCase(null, *, *) = -1 + * StrUtil.indexOfIgnoreCase(*, null, *) = -1 + * StrUtil.indexOfIgnoreCase("", "", 0) = 0 + * StrUtil.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 + * StrUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 + * StrUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 + * StrUtil.indexOfIgnoreCase("aabaabaa", "", 2) = 2 + * StrUtil.indexOfIgnoreCase("abc", "", 9) = -1 + *+ * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置 + * @return 位置 + * @since 3.2.1 + */ + public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) { + return indexOf(str, searchStr, fromIndex, true); + } + + /** + * 指定范围内查找字符串 + * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @param fromIndex 起始位置 + * @param ignoreCase 是否忽略大小写 + * @return 位置 + * @since 3.2.1 + */ + public static int indexOf(final CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) { + if (str == null || searchStr == null) { + return INDEX_NOT_FOUND; + } + if (fromIndex < 0) { + fromIndex = 0; + } + + final int endLimit = str.length() - searchStr.length() + 1; + if (fromIndex > endLimit) { + return INDEX_NOT_FOUND; + } + if (searchStr.length() == 0) { + return fromIndex; + } + + if (false == ignoreCase) { + // 不忽略大小写调用JDK方法 + return str.toString().indexOf(searchStr.toString(), fromIndex); + } + + for (int i = fromIndex; i < endLimit; i++) { + if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { + return i; + } + } + return INDEX_NOT_FOUND; + } + + /** + * 指定范围内查找字符串,忽略大小写 + * + * @param str 字符串 + * @param searchStr 需要查找位置的字符串 + * @return 位置 + * @since 3.2.1 + */ + public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { + return lastIndexOfIgnoreCase(str, searchStr, str.length()); + } + + /** + * 指定范围内查找字符串,忽略大小写
+ * 如果 str=null 或 searchStr=null 或 ordinal≥0 则返回-1
+ * 此方法来自:Apache-Commons-Lang
+ *
+ * 例子(*代表任意字符): + * + *
+ * StrUtil.ordinalIndexOf(null, *, *) = -1 + * StrUtil.ordinalIndexOf(*, null, *) = -1 + * StrUtil.ordinalIndexOf("", "", *) = 0 + * StrUtil.ordinalIndexOf("aabaabaa", "a", 1) = 0 + * StrUtil.ordinalIndexOf("aabaabaa", "a", 2) = 1 + * StrUtil.ordinalIndexOf("aabaabaa", "b", 1) = 2 + * StrUtil.ordinalIndexOf("aabaabaa", "b", 2) = 5 + * StrUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1 + * StrUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4 + * StrUtil.ordinalIndexOf("aabaabaa", "", 1) = 0 + * StrUtil.ordinalIndexOf("aabaabaa", "", 2) = 0 + *+ * + * @param str 被检查的字符串,可以为null + * @param searchStr 被查找的字符串,可以为null + * @param ordinal 第几次出现的位置 + * @return 查找到的位置 + * @since 3.2.3 + */ + public static int ordinalIndexOf(CharSequence str, CharSequence searchStr, int ordinal) { + if (str == null || searchStr == null || ordinal <= 0) { + return INDEX_NOT_FOUND; + } + if (searchStr.length() == 0) { + return 0; + } + int found = 0; + int index = INDEX_NOT_FOUND; + do { + index = indexOf(str, searchStr, index + 1, false); + if (index < 0) { + return index; + } + found++; + } while (found < ordinal); + return index; + } + + // ------------------------------------------------------------------------ remove + + /** + * 移除字符串中所有给定字符串
+ * 1. \r + * 1. \n + *+ * + * @param str 字符串 + * @return 处理后的字符串 + * @since 4.2.2 + */ + public static String removeAllLineBreaks(CharSequence str) { + return removeAll(str, CharUtil.CR, CharUtil.LF); + } + + /** + * 去掉首部指定长度的字符串并将剩余字符串首字母小写
+ * StrUtil.subSufByLength("abcde", 3) = "cde" + * StrUtil.subSufByLength("abcde", 0) = "" + * StrUtil.subSufByLength("abcde", -5) = "" + * StrUtil.subSufByLength("abcde", -1) = "" + * StrUtil.subSufByLength("abcde", 5) = "abcde" + * StrUtil.subSufByLength("abcde", 10) = "abcde" + * StrUtil.subSufByLength(null, 3) = null + *+ * + * @param string 字符串 + * @param length 切割长度 + * @return 切割后后剩余的后半部分字符串 + * @since 4.0.1 + */ + public static String subSufByLength(CharSequence string, int length) { + if (isEmpty(string)) { + return null; + } + if (length <= 0) { + return EMPTY; + } + return sub(string, -length, string.length()); + } + + /** + * 截取字符串,从指定位置开始,截取指定长度的字符串
+ * StrUtil.subBefore(null, *, false) = null + * StrUtil.subBefore("", *, false) = "" + * StrUtil.subBefore("abc", "a", false) = "" + * StrUtil.subBefore("abcba", "b", false) = "a" + * StrUtil.subBefore("abc", "c", false) = "ab" + * StrUtil.subBefore("abc", "d", false) = "abc" + * StrUtil.subBefore("abc", "", false) = "" + * StrUtil.subBefore("abc", null, false) = "abc" + *+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串(不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 + * @return 切割后的字符串 + * @since 3.1.1 + */ + public static String subBefore(CharSequence string, CharSequence separator, boolean isLastSeparator) { + if (isEmpty(string) || separator == null) { + return null == string ? null : string.toString(); + } + + final String str = string.toString(); + final String sep = separator.toString(); + if (sep.isEmpty()) { + return EMPTY; + } + final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); + if (INDEX_NOT_FOUND == pos) { + return str; + } + if (0 == pos) { + return EMPTY; + } + return str.substring(0, pos); + } + + /** + * 截取分隔字符串之前的字符串,不包括分隔字符串
+ * StrUtil.subBefore(null, *, false) = null + * StrUtil.subBefore("", *, false) = "" + * StrUtil.subBefore("abc", 'a', false) = "" + * StrUtil.subBefore("abcba", 'b', false) = "a" + * StrUtil.subBefore("abc", 'c', false) = "ab" + * StrUtil.subBefore("abc", 'd', false) = "abc" + *+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串(不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 + * @return 切割后的字符串 + * @since 4.1.15 + */ + public static String subBefore(CharSequence string, char separator, boolean isLastSeparator) { + if (isEmpty(string)) { + return null == string ? null : EMPTY; + } + + final String str = string.toString(); + final int pos = isLastSeparator ? str.lastIndexOf(separator) : str.indexOf(separator); + if (INDEX_NOT_FOUND == pos) { + return str; + } + if (0 == pos) { + return EMPTY; + } + return str.substring(0, pos); + } + + /** + * 截取分隔字符串之后的字符串,不包括分隔字符串
+ * StrUtil.subAfter(null, *, false) = null + * StrUtil.subAfter("", *, false) = "" + * StrUtil.subAfter(*, null, false) = "" + * StrUtil.subAfter("abc", "a", false) = "bc" + * StrUtil.subAfter("abcba", "b", false) = "cba" + * StrUtil.subAfter("abc", "c", false) = "" + * StrUtil.subAfter("abc", "d", false) = "" + * StrUtil.subAfter("abc", "", false) = "abc" + *+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串(不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 + * @return 切割后的字符串 + * @since 3.1.1 + */ + public static String subAfter(CharSequence string, CharSequence separator, boolean isLastSeparator) { + if (isEmpty(string)) { + return null == string ? null : EMPTY; + } + if (separator == null) { + return EMPTY; + } + final String str = string.toString(); + final String sep = separator.toString(); + final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); + if (INDEX_NOT_FOUND == pos || (string.length() - 1) == pos) { + return EMPTY; + } + return str.substring(pos + separator.length()); + } + + /** + * 截取分隔字符串之后的字符串,不包括分隔字符串
+ * StrUtil.subAfter(null, *, false) = null + * StrUtil.subAfter("", *, false) = "" + * StrUtil.subAfter("abc", 'a', false) = "bc" + * StrUtil.subAfter("abcba", 'b', false) = "cba" + * StrUtil.subAfter("abc", 'c', false) = "" + * StrUtil.subAfter("abc", 'd', false) = "" + *+ * + * @param string 被查找的字符串 + * @param separator 分隔字符串(不包括) + * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 + * @return 切割后的字符串 + * @since 4.1.15 + */ + public static String subAfter(CharSequence string, char separator, boolean isLastSeparator) { + if (isEmpty(string)) { + return null == string ? null : EMPTY; + } + final String str = string.toString(); + final int pos = isLastSeparator ? str.lastIndexOf(separator) : str.indexOf(separator); + if (INDEX_NOT_FOUND == pos) { + return EMPTY; + } + return str.substring(pos + 1); + } + + /** + * 截取指定字符串中间部分,不包括标识字符串
+ * 栗子: + * + *
+ * StrUtil.subBetween("wx[b]yz", "[", "]") = "b" + * StrUtil.subBetween(null, *, *) = null + * StrUtil.subBetween(*, null, *) = null + * StrUtil.subBetween(*, *, null) = null + * StrUtil.subBetween("", "", "") = "" + * StrUtil.subBetween("", "", "]") = null + * StrUtil.subBetween("", "[", "]") = null + * StrUtil.subBetween("yabcz", "", "") = "" + * StrUtil.subBetween("yabcz", "y", "z") = "abc" + * StrUtil.subBetween("yabczyabcz", "y", "z") = "abc" + *+ * + * @param str 被切割的字符串 + * @param before 截取开始的字符串标识 + * @param after 截取到的字符串标识 + * @return 截取后的字符串 + * @since 3.1.1 + */ + public static String subBetween(CharSequence str, CharSequence before, CharSequence after) { + if (str == null || before == null || after == null) { + return null; + } + + final String str2 = str.toString(); + final String before2 = before.toString(); + final String after2 = after.toString(); + + final int start = str2.indexOf(before2); + if (start != INDEX_NOT_FOUND) { + final int end = str2.indexOf(after2, start + before2.length()); + if (end != INDEX_NOT_FOUND) { + return str2.substring(start + before2.length(), end); + } + } + return null; + } + + /** + * 截取指定字符串中间部分,不包括标识字符串
+ * 栗子: + * + *
+ * StrUtil.subBetween(null, *) = null + * StrUtil.subBetween("", "") = "" + * StrUtil.subBetween("", "tag") = null + * StrUtil.subBetween("tagabctag", null) = null + * StrUtil.subBetween("tagabctag", "") = "" + * StrUtil.subBetween("tagabctag", "tag") = "abc" + *+ * + * @param str 被切割的字符串 + * @param beforeAndAfter 截取开始和结束的字符串标识 + * @return 截取后的字符串 + * @since 3.1.1 + */ + public static String subBetween(CharSequence str, CharSequence beforeAndAfter) { + return subBetween(str, beforeAndAfter, beforeAndAfter); + } + + /** + * 截取指定字符串多段中间部分,不包括标识字符串
+ * 栗子: + * + *
+ * StrUtil.subBetweenAll("wx[b]y[z]", "[", "]") = ["b","z"] + * StrUtil.subBetweenAll(null, *, *) = [] + * StrUtil.subBetweenAll(*, null, *) = [] + * StrUtil.subBetweenAll(*, *, null) = [] + * StrUtil.subBetweenAll("", "", "") = [] + * StrUtil.subBetweenAll("", "", "]") = [] + * StrUtil.subBetweenAll("", "[", "]") = [] + * StrUtil.subBetweenAll("yabcz", "", "") = [] + * StrUtil.subBetweenAll("yabcz", "y", "z") = ["abc"] + * StrUtil.subBetweenAll("yabczyabcz", "y", "z") = ["abc","abc"] + * StrUtil.subBetweenAll("[yabc[zy]abcz]", "[", "]"); = ["zy"] 重叠时只截取内部, + *+ * + * @param str 被切割的字符串 + * @param prefix 截取开始的字符串标识 + * @param suffix 截取到的字符串标识 + * @return 截取后的字符串 + * @author dahuoyzs + * @since 5.2.5 + */ + public static String[] subBetweenAll(CharSequence str, CharSequence prefix, CharSequence suffix) { + if (hasEmpty(str, prefix, suffix) || + // 不包含起始字符串,则肯定没有子串 + false == contains(str, prefix)) { + return new String[0]; + } + + final List
+ * 栗子: + * + *
+ * StrUtil.subBetweenAll(null, *) = [] + * StrUtil.subBetweenAll(*, null) = [] + * StrUtil.subBetweenAll(*, *) = [] + * StrUtil.subBetweenAll("", "") = [] + * StrUtil.subBetweenAll("", "#") = [] + * StrUtil.subBetweenAll("gotanks", "") = [] + * StrUtil.subBetweenAll("#gotanks#", "#") = ["gotanks"] + * StrUtil.subBetweenAll("#hello# #world#!", "#") = ["hello", "world"] + * StrUtil.subBetweenAll("#hello# world#!", "#"); = ["hello"] + *+ * + * @param str 被切割的字符串 + * @param prefixAndSuffix 截取开始和结束的字符串标识 + * @return 截取后的字符串 + * @author gotanks + * @since 5.5.0 + */ + public static String[] subBetweenAll(CharSequence str, CharSequence prefixAndSuffix) { + return subBetweenAll(str, prefixAndSuffix, prefixAndSuffix); + } + + // ------------------------------------------------------------------------ repeat + + /** + * 重复某个字符 + * + * @param c 被重复的字符 + * @param count 重复的数目,如果小于等于0则返回"" + * @return 重复字符字符串 + */ + public static String repeat(char c, int count) { + if (count <= 0) { + return EMPTY; + } + + char[] result = new char[count]; + for (int i = 0; i < count; i++) { + result[i] = c; + } + return new String(result); + } + + /** + * 重复某个字符串 + * + * @param str 被重复的字符 + * @param count 重复的数目 + * @return 重复字符字符串 + */ + public static String repeat(CharSequence str, int count) { + if (null == str) { + return null; + } + if (count <= 0 || str.length() == 0) { + return EMPTY; + } + if (count == 1) { + return str.toString(); + } + + // 检查 + final int len = str.length(); + final long longSize = (long) len * (long) count; + final int size = (int) longSize; + if (size != longSize) { + throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize); + } + + final char[] array = new char[size]; + str.toString().getChars(0, len, array, 0); + int n; + for (n = len; n < size - n; n <<= 1) {// n <<= 1相当于n *2 + System.arraycopy(array, 0, array, n, n); + } + System.arraycopy(array, 0, array, n, size - n); + return new String(array); + } + + /** + * 重复某个字符串到指定长度 + * + * @param str 被重复的字符 + * @param padLen 指定长度 + * @return 重复字符字符串 + * @since 4.3.2 + */ + public static String repeatByLength(CharSequence str, int padLen) { + if (null == str) { + return null; + } + if (padLen <= 0) { + return StrUtil.EMPTY; + } + final int strLen = str.length(); + if (strLen == padLen) { + return str.toString(); + } else if (strLen > padLen) { + return subPre(str, padLen); + } + + // 重复,直到达到指定长度 + final char[] padding = new char[padLen]; + for (int i = 0; i < padLen; i++) { + padding[i] = str.charAt(i % strLen); + } + return new String(padding); + } + + /** + * 重复某个字符串并通过分界符连接 + * + *
+ * StrUtil.repeatAndJoin("?", 5, ",") = "?,?,?,?,?" + * StrUtil.repeatAndJoin("?", 0, ",") = "" + * StrUtil.repeatAndJoin("?", 5, null) = "?????" + *+ * + * @param str 被重复的字符串 + * @param count 数量 + * @param conjunction 分界符 + * @return 连接后的字符串 + * @since 4.0.1 + */ + public static String repeatAndJoin(CharSequence str, int count, CharSequence conjunction) { + if (count <= 0) { + return EMPTY; + } + final StrBuilder builder = StrBuilder.create(); + boolean isFirst = true; + while (count-- > 0) { + if (isFirst) { + isFirst = false; + } else if (isNotEmpty(conjunction)) { + builder.append(conjunction); + } + builder.append(str); + } + return builder.toString(); + } + + // ------------------------------------------------------------------------ equals + + /** + * 比较两个字符串(大小写敏感)。 + * + *
+ * equals(null, null) = true + * equals(null, "abc") = false + * equals("abc", null) = false + * equals("abc", "abc") = true + * equals("abc", "ABC") = false + *+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} + */ + public static boolean equals(CharSequence str1, CharSequence str2) { + return equals(str1, str2, false); + } + + /** + * 比较两个字符串(大小写不敏感)。 + * + *
+ * equalsIgnoreCase(null, null) = true + * equalsIgnoreCase(null, "abc") = false + * equalsIgnoreCase("abc", null) = false + * equalsIgnoreCase("abc", "abc") = true + * equalsIgnoreCase("abc", "ABC") = true + *+ * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} + */ + public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) { + return equals(str1, str2, true); + } + + /** + * 比较两个字符串是否相等。 + * + * @param str1 要比较的字符串1 + * @param str2 要比较的字符串2 + * @param ignoreCase 是否忽略大小写 + * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} + * @since 3.2.0 + */ + public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) { + if (null == str1) { + // 只有两个都为null才判断相等 + return str2 == null; + } + if (null == str2) { + // 字符串2空,字符串1非空,直接false + return false; + } + + if (ignoreCase) { + return str1.toString().equalsIgnoreCase(str2.toString()); + } else { + return str1.toString().contentEquals(str2); + } + } + + /** + * 给定字符串是否与提供的中任一字符串相同(忽略大小写),相同则返回{@code true},没有相同的返回{@code false}
+ * StrUtil.padPre(null, *, *);//null + * StrUtil.padPre("1", 3, "ABC");//"AB1" + * StrUtil.padPre("123", 2, "ABC");//"12" + *+ * + * @param str 字符串 + * @param minLength 最小长度 + * @param padStr 补充的字符 + * @return 补充后的字符串 + */ + public static String padPre(CharSequence str, int minLength, CharSequence padStr) { + if (null == str) { + return null; + } + final int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return subPre(str, minLength); + } + + return repeatByLength(padStr, minLength - strLen).concat(str.toString()); + } + + /** + * 补充字符串以满足最小长度 + * + *
+ * StrUtil.padPre(null, *, *);//null + * StrUtil.padPre("1", 3, '0');//"001" + * StrUtil.padPre("123", 2, '0');//"12" + *+ * + * @param str 字符串 + * @param minLength 最小长度 + * @param padChar 补充的字符 + * @return 补充后的字符串 + */ + public static String padPre(CharSequence str, int minLength, char padChar) { + if (null == str) { + return null; + } + final int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return subPre(str, minLength); + } + + return repeat(padChar, minLength - strLen).concat(str.toString()); + } + + /** + * 补充字符串以满足最小长度 + * + *
+ * StrUtil.padAfter(null, *, *);//null + * StrUtil.padAfter("1", 3, '0');//"100" + * StrUtil.padAfter("123", 2, '0');//"23" + *+ * + * @param str 字符串,如果为{@code null},直接返回null + * @param minLength 最小长度 + * @param padChar 补充的字符 + * @return 补充后的字符串 + */ + public static String padAfter(CharSequence str, int minLength, char padChar) { + if (null == str) { + return null; + } + final int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return sub(str, strLen - minLength, strLen); + } + + return str.toString().concat(repeat(padChar, minLength - strLen)); + } + + /** + * 补充字符串以满足最小长度 + * + *
+ * StrUtil.padAfter(null, *, *);//null + * StrUtil.padAfter("1", 3, "ABC");//"1AB" + * StrUtil.padAfter("123", 2, "ABC");//"23" + *+ * + * @param str 字符串,如果为{@code null},直接返回null + * @param minLength 最小长度 + * @param padStr 补充的字符 + * @return 补充后的字符串 + * @since 4.3.2 + */ + public static String padAfter(CharSequence str, int minLength, CharSequence padStr) { + if (null == str) { + return null; + } + final int strLen = str.length(); + if (strLen == minLength) { + return str.toString(); + } else if (strLen > minLength) { + return subSufByLength(str, minLength); + } + + return str.toString().concat(repeatByLength(padStr, minLength - strLen)); + } + + // ------------------------------------------------------------------------ center + + /** + * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 + * + *
+ * StrUtil.center(null, *) = null + * StrUtil.center("", 4) = " " + * StrUtil.center("ab", -1) = "ab" + * StrUtil.center("ab", 4) = " ab " + * StrUtil.center("abcd", 2) = "abcd" + * StrUtil.center("a", 4) = " a " + *+ * + * @param str 字符串 + * @param size 指定长度 + * @return 补充后的字符串 + * @since 4.3.2 + */ + public static String center(CharSequence str, final int size) { + return center(str, size, CharUtil.SPACE); + } + + /** + * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 + * + *
+ * StrUtil.center(null, *, *) = null + * StrUtil.center("", 4, ' ') = " " + * StrUtil.center("ab", -1, ' ') = "ab" + * StrUtil.center("ab", 4, ' ') = " ab " + * StrUtil.center("abcd", 2, ' ') = "abcd" + * StrUtil.center("a", 4, ' ') = " a " + * StrUtil.center("a", 4, 'y') = "yayy" + * StrUtil.center("abc", 7, ' ') = " abc " + *+ * + * @param str 字符串 + * @param size 指定长度 + * @param padChar 两边补充的字符 + * @return 补充后的字符串 + * @since 4.3.2 + */ + public static String center(CharSequence str, final int size, char padChar) { + if (str == null || size <= 0) { + return str(str); + } + final int strLen = str.length(); + final int pads = size - strLen; + if (pads <= 0) { + return str.toString(); + } + str = padPre(str, strLen + pads / 2, padChar); + str = padAfter(str, size, padChar); + return str.toString(); + } + + /** + * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 + * + *
+ * StrUtil.center(null, *, *) = null + * StrUtil.center("", 4, " ") = " " + * StrUtil.center("ab", -1, " ") = "ab" + * StrUtil.center("ab", 4, " ") = " ab " + * StrUtil.center("abcd", 2, " ") = "abcd" + * StrUtil.center("a", 4, " ") = " a " + * StrUtil.center("a", 4, "yz") = "yayz" + * StrUtil.center("abc", 7, null) = " abc " + * StrUtil.center("abc", 7, "") = " abc " + *+ * + * @param str 字符串 + * @param size 指定长度 + * @param padStr 两边补充的字符串 + * @return 补充后的字符串 + */ + public static String center(CharSequence str, final int size, CharSequence padStr) { + if (str == null || size <= 0) { + return str(str); + } + if (isEmpty(padStr)) { + padStr = SPACE; + } + final int strLen = str.length(); + final int pads = size - strLen; + if (pads <= 0) { + return str.toString(); + } + str = padPre(str, strLen + pads / 2, padStr); + str = padAfter(str, size, padStr); + return str.toString(); + } + + // ------------------------------------------------------------------------ str + + /** + * {@link CharSequence} 转为字符串,null安全 + * + * @param cs {@link CharSequence} + * @return 字符串 + */ + public static String str(CharSequence cs) { + return null == cs ? null : cs.toString(); + } + + // ------------------------------------------------------------------------ count + + /** + * 统计指定内容中包含指定字符串的数量
+ * StrUtil.count(null, *) = 0 + * StrUtil.count("", *) = 0 + * StrUtil.count("abba", null) = 0 + * StrUtil.count("abba", "") = 0 + * StrUtil.count("abba", "a") = 2 + * StrUtil.count("abba", "ab") = 1 + * StrUtil.count("abba", "xxx") = 0 + *+ * + * @param content 被查找的字符串 + * @param strForSearch 需要查找的字符串 + * @return 查找到的个数 + */ + public static int count(CharSequence content, CharSequence strForSearch) { + if (hasEmpty(content, strForSearch) || strForSearch.length() > content.length()) { + return 0; + } + + int count = 0; + int idx = 0; + final String content2 = content.toString(); + final String strForSearch2 = strForSearch.toString(); + while ((idx = content2.indexOf(strForSearch2, idx)) > -1) { + count++; + idx += strForSearch.length(); + } + return count; + } + + /** + * 统计指定内容中包含指定字符的数量 + * + * @param content 内容 + * @param charForSearch 被统计的字符 + * @return 包含数量 + */ + public static int count(CharSequence content, char charForSearch) { + int count = 0; + if (isEmpty(content)) { + return 0; + } + int contentLength = content.length(); + for (int i = 0; i < contentLength; i++) { + if (charForSearch == content.charAt(i)) { + count++; + } + } + return count; + } + + // ------------------------------------------------------------------------ compare + + /** + * 比较两个字符串,用于排序 + * + *
+ * StrUtil.compare(null, null, *) = 0 + * StrUtil.compare(null , "a", true) < 0 + * StrUtil.compare(null , "a", false) > 0 + * StrUtil.compare("a", null, true) > 0 + * StrUtil.compare("a", null, false) < 0 + * StrUtil.compare("abc", "abc", *) = 0 + * StrUtil.compare("a", "b", *) < 0 + * StrUtil.compare("b", "a", *) > 0 + * StrUtil.compare("a", "B", *) > 0 + * StrUtil.compare("ab", "abc", *) < 0 + *+ * + * @param str1 字符串1 + * @param str2 字符串2 + * @param nullIsLess {@code null} 值是否排在前(null是否小于非空值) + * @return 排序值。负数:str1 < str2,正数:str1 > str2, 0:str1 == str2 + */ + public static int compare(final CharSequence str1, final CharSequence str2, final boolean nullIsLess) { + if (str1 == str2) { + return 0; + } + if (str1 == null) { + return nullIsLess ? -1 : 1; + } + if (str2 == null) { + return nullIsLess ? 1 : -1; + } + return str1.toString().compareTo(str2.toString()); + } + + /** + * 比较两个字符串,用于排序,大小写不敏感 + * + *
+ * StrUtil.compareIgnoreCase(null, null, *) = 0 + * StrUtil.compareIgnoreCase(null , "a", true) < 0 + * StrUtil.compareIgnoreCase(null , "a", false) > 0 + * StrUtil.compareIgnoreCase("a", null, true) > 0 + * StrUtil.compareIgnoreCase("a", null, false) < 0 + * StrUtil.compareIgnoreCase("abc", "abc", *) = 0 + * StrUtil.compareIgnoreCase("abc", "ABC", *) = 0 + * StrUtil.compareIgnoreCase("a", "b", *) < 0 + * StrUtil.compareIgnoreCase("b", "a", *) > 0 + * StrUtil.compareIgnoreCase("a", "B", *) < 0 + * StrUtil.compareIgnoreCase("A", "b", *) < 0 + * StrUtil.compareIgnoreCase("ab", "abc", *) < 0 + *+ * + * @param str1 字符串1 + * @param str2 字符串2 + * @param nullIsLess {@code null} 值是否排在前(null是否小于非空值) + * @return 排序值。负数:str1 < str2,正数:str1 > str2, 0:str1 == str2 + */ + public static int compareIgnoreCase(CharSequence str1, CharSequence str2, boolean nullIsLess) { + if (str1 == str2) { + return 0; + } + if (str1 == null) { + return nullIsLess ? -1 : 1; + } + if (str2 == null) { + return nullIsLess ? 1 : -1; + } + return str1.toString().compareToIgnoreCase(str2.toString()); + } + + /** + * 比较两个版本
+ * StrUtil.compareVersion(null, "v1") < 0 + * StrUtil.compareVersion("v1", "v1") = 0 + * StrUtil.compareVersion(null, null) = 0 + * StrUtil.compareVersion("v1", null) > 0 + * StrUtil.compareVersion("1.0.0", "1.0.2") < 0 + * StrUtil.compareVersion("1.0.2", "1.0.2a") < 0 + * StrUtil.compareVersion("1.13.0", "1.12.1c") > 0 + * StrUtil.compareVersion("V0.0.20170102", "V0.0.20170101") > 0 + *+ * + * @param version1 版本1 + * @param version2 版本2 + * @return 排序值。负数:version1 < version2,正数:version1 > version2, 0:version1 == version2 + * @since 4.0.2 + */ + public static int compareVersion(CharSequence version1, CharSequence version2) { + return VersionComparator.INSTANCE.compare(str(version1), str(version2)); + } + + // ------------------------------------------------------------------------ append and prepend + + /** + * 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串
+ * 1. 大写字母包括A-Z + * 2. 其它非字母的Unicode符都算作大写 + *+ * + * @param str 被检查的字符串 + * @return 是否全部为大写 + * @since 4.2.2 + */ + public static boolean isUpperCase(CharSequence str) { + if (null == str) { + return false; + } + final int len = str.length(); + for (int i = 0; i < len; i++) { + if (Character.isLowerCase(str.charAt(i))) { + return false; + } + } + return true; + } + + /** + * 给定字符串中的字母是否全部为小写,判断依据如下: + * + *
+ * 1. 小写字母包括a-z + * 2. 其它非字母的Unicode符都算作小写 + *+ * + * @param str 被检查的字符串 + * @return 是否全部为小写 + * @since 4.2.2 + */ + public static boolean isLowerCase(CharSequence str) { + if (null == str) { + return false; + } + final int len = str.length(); + for (int i = 0; i < len; i++) { + if (Character.isUpperCase(str.charAt(i))) { + return false; + } + } + return true; + } + + /** + * 切换给定字符串中的大小写。大写转小写,小写转大写。 + * + *
+ * StrUtil.swapCase(null) = null + * StrUtil.swapCase("") = "" + * StrUtil.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" + *+ * + * @param str 字符串 + * @return 交换后的字符串 + * @since 4.3.2 + */ + public static String swapCase(final String str) { + if (isEmpty(str)) { + return str; + } + + final char[] buffer = str.toCharArray(); + + for (int i = 0; i < buffer.length; i++) { + final char ch = buffer[i]; + if (Character.isUpperCase(ch)) { + buffer[i] = Character.toLowerCase(ch); + } else if (Character.isTitleCase(ch)) { + buffer[i] = Character.toLowerCase(ch); + } else if (Character.isLowerCase(ch)) { + buffer[i] = Character.toUpperCase(ch); + } + } + return new String(buffer); + } + + /** + * 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
+ * HelloWorld=》hello_world + * Hello_World=》hello_world + * HelloWorld_test=》hello_world_test + *+ * + * @param str 转换前的驼峰式命名的字符串,也可以为下划线形式 + * @return 转换后下划线方式命名的字符串 + */ + public static String toUnderlineCase(CharSequence str) { + return toSymbolCase(str, CharUtil.UNDERLINE); + } + + /** + * 将驼峰式命名的字符串转换为使用符号连接方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
+ * getName =》name + * setName =》name + * isName =》name + *+ * + * @param getOrSetMethodName Get或Set方法名 + * @return 如果是set或get方法名,返回field, 否则null + */ + public static String getGeneralField(CharSequence getOrSetMethodName) { + final String getOrSetMethodNameStr = getOrSetMethodName.toString(); + if (getOrSetMethodNameStr.startsWith("get") || getOrSetMethodNameStr.startsWith("set")) { + return removePreAndLowerFirst(getOrSetMethodName, 3); + } else if (getOrSetMethodNameStr.startsWith("is")) { + return removePreAndLowerFirst(getOrSetMethodName, 2); + } + return null; + } + + /** + * 生成set方法名
字符串是否为空白,空白的定义如下:
- *例:
- *注意:该方法与 {@link #isEmpty(CharSequence)} 的区别是: - * 该方法会校验空白字符,且性能相对于 {@link #isEmpty(CharSequence)} 略慢。
- *建议:
- *如果对象是字符串是否为空白,空白的定义如下:
*字符串是否为非空白,非空白的定义如下:
- *例:
- *注意:该方法与 {@link #isNotEmpty(CharSequence)} 的区别是: - * 该方法会校验空白字符,且性能相对于 {@link #isNotEmpty(CharSequence)} 略慢。
- *建议:仅对于客户端(或第三方接口)传入的参数使用该方法。
- * - * @param str 被检测的字符串 - * @return 是否为非空 - * @see StrUtil#isBlank(CharSequence) - */ - public static boolean isNotBlank(CharSequence str) { - return false == isBlank(str); - } - - /** - *指定字符串数组中,是否包含空字符串。
- *如果指定的字符串数组的长度为 0,或者其中的任意一个元素是空字符串,则返回 true。
- *例:
- *注意:该方法与 {@link #isAllBlank(CharSequence...)} 的区别在于:
- *指定字符串数组中的元素,是否全部为空字符串。
- *如果指定的字符串数组的长度为 0,或者所有元素都是空字符串,则返回 true。
- *例:
- *注意:该方法与 {@link #hasBlank(CharSequence...)} 的区别在于:
- *字符串是否为空,空的定义如下:
- *例:
- *注意:该方法与 {@link #isBlank(CharSequence)} 的区别是:该方法不校验空白字符。
- *建议:
- *如果对象是字符串是否为空串,空的定义如下:
字符串是否为非空白,非空白的定义如下:
- *例:
- *注意:该方法与 {@link #isNotBlank(CharSequence)} 的区别是:该方法不校验空白字符。
- *建议:该方法建议用于工具类或任何可以预期的方法参数的校验中。
- * - * @param str 被检测的字符串 - * @return 是否为非空 - * @see StrUtil#isEmpty(CharSequence) - */ - public static boolean isNotEmpty(CharSequence str) { - return false == isEmpty(str); - } - - /** - * 当给定字符串为null时,转换为Empty - * - * @param str 被检查的字符串 - * @return 原字符串或者空串 - * @see #nullToEmpty(CharSequence) - * @since 4.6.3 - */ - public static String emptyIfNull(CharSequence str) { - return nullToEmpty(str); - } - - /** - * 当给定字符串为null时,转换为Empty - * - * @param str 被转换的字符串 - * @return 转换后的字符串 - */ - public static String nullToEmpty(CharSequence str) { - return nullToDefault(str, EMPTY); - } - - /** - * 如果字符串是 {@code null},则返回指定默认字符串,否则返回字符串本身。 - * - *- * nullToDefault(null, "default") = "default" - * nullToDefault("", "default") = "" - * nullToDefault(" ", "default") = " " - * nullToDefault("bat", "default") = "bat" - *- * - * @param str 要转换的字符串 - * @param defaultStr 默认字符串 - * @return 字符串本身或指定的默认字符串 - */ - public static String nullToDefault(CharSequence str, String defaultStr) { - return (str == null) ? defaultStr : str.toString(); - } - - /** - * 如果字符串是{@code null}或者"",则返回指定默认字符串,否则返回字符串本身。 - * - *
- * emptyToDefault(null, "default") = "default" - * emptyToDefault("", "default") = "default" - * emptyToDefault(" ", "default") = " " - * emptyToDefault("bat", "default") = "bat" - *- * - * @param str 要转换的字符串 - * @param defaultStr 默认字符串 - * @return 字符串本身或指定的默认字符串 - * @since 4.1.0 - */ - public static String emptyToDefault(CharSequence str, String defaultStr) { - return isEmpty(str) ? defaultStr : str.toString(); - } - - /** - * 如果字符串是{@code null}或者""或者空白,则返回指定默认字符串,否则返回字符串本身。 - * - *
- * emptyToDefault(null, "default") = "default" - * emptyToDefault("", "default") = "default" - * emptyToDefault(" ", "default") = "default" - * emptyToDefault("bat", "default") = "bat" - *- * - * @param str 要转换的字符串 - * @param defaultStr 默认字符串 - * @return 字符串本身或指定的默认字符串 - * @since 4.1.0 - */ - public static String blankToDefault(CharSequence str, String defaultStr) { - return isBlank(str) ? defaultStr : str.toString(); - } - - /** - * 当给定字符串为空字符串时,转换为{@code null} - * - * @param str 被转换的字符串 - * @return 转换后的字符串 - */ - public static String emptyToNull(CharSequence str) { - return isEmpty(str) ? null : str.toString(); - } - - /** - *
是否包含空字符串。
- *如果指定的字符串数组的长度为 0,或者其中的任意一个元素是空字符串,则返回 true。
- *例:
- *注意:该方法与 {@link #isAllEmpty(CharSequence...)} 的区别在于:
- *指定字符串数组中的元素,是否全部为空字符串。
- *如果指定的字符串数组的长度为 0,或者所有元素都是空字符串,则返回 true。
- *例:
- *注意:该方法与 {@link #hasEmpty(CharSequence...)} 的区别在于:
- *指定字符串数组中的元素,是否都不为空字符串。
- *如果指定的字符串数组的长度不为 0,或者所有元素都不是空字符串,则返回 true。
- *例:
- *注意:该方法与 {@link #isAllEmpty(CharSequence...)} 的区别在于:
- *- * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *
- * trim(null) = null - * trim("") = "" - * trim(" ") = "" - * trim("abc") = "abc" - * trim(" abc ") = "abc" - *- * - * @param str 要处理的字符串 - * @return 除去头尾空白的字符串,如果原字串为{@code null},则返回{@code null} - */ - public static String trim(CharSequence str) { - return (null == str) ? null : trim(str, 0); - } - /** * 给定字符串数组全部做去首尾空格 * @@ -807,2044 +298,11 @@ public class StrUtil { for (int i = 0; i < strs.length; i++) { str = strs[i]; if (null != str) { - strs[i] = str.trim(); + strs[i] = trim(str); } } } - /** - * 除去字符串头尾部的空白,如果字符串是{@code null},返回{@code ""}。 - * - *
- * StrUtil.trimToEmpty(null) = "" - * StrUtil.trimToEmpty("") = "" - * StrUtil.trimToEmpty(" ") = "" - * StrUtil.trimToEmpty("abc") = "abc" - * StrUtil.trimToEmpty(" abc ") = "abc" - *- * - * @param str 字符串 - * @return 去除两边空白符后的字符串, 如果为null返回"" - * @since 3.1.1 - */ - public static String trimToEmpty(CharSequence str) { - return str == null ? EMPTY : trim(str); - } - - /** - * 除去字符串头尾部的空白,如果字符串是{@code null}或者"",返回{@code null}。 - * - *
- * StrUtil.trimToNull(null) = null - * StrUtil.trimToNull("") = null - * StrUtil.trimToNull(" ") = null - * StrUtil.trimToNull("abc") = "abc" - * StrUtil.trimToEmpty(" abc ") = "abc" - *- * - * @param str 字符串 - * @return 去除两边空白符后的字符串, 如果为空返回null - * @since 3.2.1 - */ - public static String trimToNull(CharSequence str) { - final String trimStr = trim(str); - return EMPTY.equals(trimStr) ? null : trimStr; - } - - /** - * 除去字符串头部的空白,如果字符串是{@code null},则返回{@code null}。 - * - *
- * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *
- * trimStart(null) = null - * trimStart("") = "" - * trimStart("abc") = "abc" - * trimStart(" abc") = "abc" - * trimStart("abc ") = "abc " - * trimStart(" abc ") = "abc " - *- * - * @param str 要处理的字符串 - * @return 除去空白的字符串,如果原字串为{@code null}或结果字符串为{@code ""},则返回 {@code null} - */ - public static String trimStart(CharSequence str) { - return trim(str, -1); - } - - /** - * 除去字符串尾部的空白,如果字符串是{@code null},则返回{@code null}。 - * - *
- * 注意,和{@link String#trim()}不同,此方法使用{@link CharUtil#isBlankChar(char)} 来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。 - * - *
- * trimEnd(null) = null - * trimEnd("") = "" - * trimEnd("abc") = "abc" - * trimEnd(" abc") = " abc" - * trimEnd("abc ") = "abc" - * trimEnd(" abc ") = " abc" - *- * - * @param str 要处理的字符串 - * @return 除去空白的字符串,如果原字串为{@code null}或结果字符串为{@code ""},则返回 {@code null} - */ - public static String trimEnd(CharSequence str) { - return trim(str, 1); - } - - /** - * 除去字符串头尾部的空白符,如果字符串是{@code null},依然返回{@code null}。 - * - * @param str 要处理的字符串 - * @param mode {@code -1}表示trimStart,{@code 0}表示trim全部, {@code 1}表示trimEnd - * @return 除去指定字符后的的字符串,如果原字串为{@code null},则返回{@code null} - */ - public static String trim(CharSequence str, int mode) { - String result; - if (str == null) { - result = null; - } else { - int length = str.length(); - int start = 0; - int end = length;// 扫描字符串头部 - if (mode <= 0) { - while ((start < end) && (CharUtil.isBlankChar(str.charAt(start)))) { - start++; - } - }// 扫描字符串尾部 - if (mode >= 0) { - while ((start < end) && (CharUtil.isBlankChar(str.charAt(end - 1)))) { - end--; - } - } - if ((start > 0) || (end < length)) { - result = str.toString().substring(start, end); - } else { - result = str.toString(); - } - } - - return result; - } - - /** - * 字符串是否以给定字符开始 - * - * @param str 字符串 - * @param c 字符 - * @return 是否开始 - */ - public static boolean startWith(CharSequence str, char c) { - if (isEmpty(str)) { - return false; - } - return c == str.charAt(0); - } - - /** - * 是否以指定字符串开头
- * getName =》name - * setName =》name - * isName =》name - *- * - * @param getOrSetMethodName Get或Set方法名 - * @return 如果是set或get方法名,返回field, 否则null - */ - public static String getGeneralField(CharSequence getOrSetMethodName) { - final String getOrSetMethodNameStr = getOrSetMethodName.toString(); - if (getOrSetMethodNameStr.startsWith("get") || getOrSetMethodNameStr.startsWith("set")) { - return removePreAndLowerFirst(getOrSetMethodName, 3); - } else if (getOrSetMethodNameStr.startsWith("is")) { - return removePreAndLowerFirst(getOrSetMethodName, 2); - } - return null; - } - - /** - * 生成set方法名
- * 1. \r - * 1. \n - *- * - * @param str 字符串 - * @return 处理后的字符串 - * @since 4.2.2 - */ - public static String removeAllLineBreaks(CharSequence str) { - return removeAll(str, C_CR, C_LF); - } - - /** - * 去掉首部指定长度的字符串并将剩余字符串首字母小写
- * StrUtil.subSufByLength("abcde", 3) = "cde" - * StrUtil.subSufByLength("abcde", 0) = "" - * StrUtil.subSufByLength("abcde", -5) = "" - * StrUtil.subSufByLength("abcde", -1) = "" - * StrUtil.subSufByLength("abcde", 5) = "abcde" - * StrUtil.subSufByLength("abcde", 10) = "abcde" - * StrUtil.subSufByLength(null, 3) = null - *- * - * @param string 字符串 - * @param length 切割长度 - * @return 切割后后剩余的后半部分字符串 - * @since 4.0.1 - */ - public static String subSufByLength(CharSequence string, int length) { - if (isEmpty(string)) { - return null; - } - if (length <= 0) { - return EMPTY; - } - return sub(string, -length, string.length()); - } - - /** - * 截取字符串,从指定位置开始,截取指定长度的字符串
- * StrUtil.subBefore(null, *, false) = null - * StrUtil.subBefore("", *, false) = "" - * StrUtil.subBefore("abc", "a", false) = "" - * StrUtil.subBefore("abcba", "b", false) = "a" - * StrUtil.subBefore("abc", "c", false) = "ab" - * StrUtil.subBefore("abc", "d", false) = "abc" - * StrUtil.subBefore("abc", "", false) = "" - * StrUtil.subBefore("abc", null, false) = "abc" - *- * - * @param string 被查找的字符串 - * @param separator 分隔字符串(不包括) - * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 - * @return 切割后的字符串 - * @since 3.1.1 - */ - public static String subBefore(CharSequence string, CharSequence separator, boolean isLastSeparator) { - if (isEmpty(string) || separator == null) { - return null == string ? null : string.toString(); - } - - final String str = string.toString(); - final String sep = separator.toString(); - if (sep.isEmpty()) { - return EMPTY; - } - final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); - if (INDEX_NOT_FOUND == pos) { - return str; - } - if (0 == pos) { - return EMPTY; - } - return str.substring(0, pos); - } - - /** - * 截取分隔字符串之前的字符串,不包括分隔字符串
- * StrUtil.subBefore(null, *, false) = null - * StrUtil.subBefore("", *, false) = "" - * StrUtil.subBefore("abc", 'a', false) = "" - * StrUtil.subBefore("abcba", 'b', false) = "a" - * StrUtil.subBefore("abc", 'c', false) = "ab" - * StrUtil.subBefore("abc", 'd', false) = "abc" - *- * - * @param string 被查找的字符串 - * @param separator 分隔字符串(不包括) - * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 - * @return 切割后的字符串 - * @since 4.1.15 - */ - public static String subBefore(CharSequence string, char separator, boolean isLastSeparator) { - if (isEmpty(string)) { - return null == string ? null : EMPTY; - } - - final String str = string.toString(); - final int pos = isLastSeparator ? str.lastIndexOf(separator) : str.indexOf(separator); - if (INDEX_NOT_FOUND == pos) { - return str; - } - if (0 == pos) { - return EMPTY; - } - return str.substring(0, pos); - } - - /** - * 截取分隔字符串之后的字符串,不包括分隔字符串
- * StrUtil.subAfter(null, *, false) = null - * StrUtil.subAfter("", *, false) = "" - * StrUtil.subAfter(*, null, false) = "" - * StrUtil.subAfter("abc", "a", false) = "bc" - * StrUtil.subAfter("abcba", "b", false) = "cba" - * StrUtil.subAfter("abc", "c", false) = "" - * StrUtil.subAfter("abc", "d", false) = "" - * StrUtil.subAfter("abc", "", false) = "abc" - *- * - * @param string 被查找的字符串 - * @param separator 分隔字符串(不包括) - * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 - * @return 切割后的字符串 - * @since 3.1.1 - */ - public static String subAfter(CharSequence string, CharSequence separator, boolean isLastSeparator) { - if (isEmpty(string)) { - return null == string ? null : EMPTY; - } - if (separator == null) { - return EMPTY; - } - final String str = string.toString(); - final String sep = separator.toString(); - final int pos = isLastSeparator ? str.lastIndexOf(sep) : str.indexOf(sep); - if (INDEX_NOT_FOUND == pos || (string.length() - 1) == pos) { - return EMPTY; - } - return str.substring(pos + separator.length()); - } - - /** - * 截取分隔字符串之后的字符串,不包括分隔字符串
- * StrUtil.subAfter(null, *, false) = null - * StrUtil.subAfter("", *, false) = "" - * StrUtil.subAfter("abc", 'a', false) = "bc" - * StrUtil.subAfter("abcba", 'b', false) = "cba" - * StrUtil.subAfter("abc", 'c', false) = "" - * StrUtil.subAfter("abc", 'd', false) = "" - *- * - * @param string 被查找的字符串 - * @param separator 分隔字符串(不包括) - * @param isLastSeparator 是否查找最后一个分隔字符串(多次出现分隔字符串时选取最后一个),true为选取最后一个 - * @return 切割后的字符串 - * @since 4.1.15 - */ - public static String subAfter(CharSequence string, char separator, boolean isLastSeparator) { - if (isEmpty(string)) { - return null == string ? null : EMPTY; - } - final String str = string.toString(); - final int pos = isLastSeparator ? str.lastIndexOf(separator) : str.indexOf(separator); - if (INDEX_NOT_FOUND == pos) { - return EMPTY; - } - return str.substring(pos + 1); - } - - /** - * 截取指定字符串中间部分,不包括标识字符串
- * 栗子: - * - *
- * StrUtil.subBetween("wx[b]yz", "[", "]") = "b" - * StrUtil.subBetween(null, *, *) = null - * StrUtil.subBetween(*, null, *) = null - * StrUtil.subBetween(*, *, null) = null - * StrUtil.subBetween("", "", "") = "" - * StrUtil.subBetween("", "", "]") = null - * StrUtil.subBetween("", "[", "]") = null - * StrUtil.subBetween("yabcz", "", "") = "" - * StrUtil.subBetween("yabcz", "y", "z") = "abc" - * StrUtil.subBetween("yabczyabcz", "y", "z") = "abc" - *- * - * @param str 被切割的字符串 - * @param before 截取开始的字符串标识 - * @param after 截取到的字符串标识 - * @return 截取后的字符串 - * @since 3.1.1 - */ - public static String subBetween(CharSequence str, CharSequence before, CharSequence after) { - if (str == null || before == null || after == null) { - return null; - } - - final String str2 = str.toString(); - final String before2 = before.toString(); - final String after2 = after.toString(); - - final int start = str2.indexOf(before2); - if (start != INDEX_NOT_FOUND) { - final int end = str2.indexOf(after2, start + before2.length()); - if (end != INDEX_NOT_FOUND) { - return str2.substring(start + before2.length(), end); - } - } - return null; - } - - /** - * 截取指定字符串中间部分,不包括标识字符串
- * 栗子: - * - *
- * StrUtil.subBetween(null, *) = null - * StrUtil.subBetween("", "") = "" - * StrUtil.subBetween("", "tag") = null - * StrUtil.subBetween("tagabctag", null) = null - * StrUtil.subBetween("tagabctag", "") = "" - * StrUtil.subBetween("tagabctag", "tag") = "abc" - *- * - * @param str 被切割的字符串 - * @param beforeAndAfter 截取开始和结束的字符串标识 - * @return 截取后的字符串 - * @since 3.1.1 - */ - public static String subBetween(CharSequence str, CharSequence beforeAndAfter) { - return subBetween(str, beforeAndAfter, beforeAndAfter); - } - - /** - * 截取指定字符串多段中间部分,不包括标识字符串
- * 栗子: - * - *
- * StrUtil.subBetweenAll("wx[b]y[z]", "[", "]") = ["b","z"] - * StrUtil.subBetweenAll(null, *, *) = [] - * StrUtil.subBetweenAll(*, null, *) = [] - * StrUtil.subBetweenAll(*, *, null) = [] - * StrUtil.subBetweenAll("", "", "") = [] - * StrUtil.subBetweenAll("", "", "]") = [] - * StrUtil.subBetweenAll("", "[", "]") = [] - * StrUtil.subBetweenAll("yabcz", "", "") = [] - * StrUtil.subBetweenAll("yabcz", "y", "z") = ["abc"] - * StrUtil.subBetweenAll("yabczyabcz", "y", "z") = ["abc","abc"] - * StrUtil.subBetweenAll("[yabc[zy]abcz]", "[", "]"); = ["zy"] 重叠时只截取内部, - *- * - * @param str 被切割的字符串 - * @param prefix 截取开始的字符串标识 - * @param suffix 截取到的字符串标识 - * @return 截取后的字符串 - * @author dahuoyzs - * @since 5.2.5 - */ - public static String[] subBetweenAll(CharSequence str, CharSequence prefix, CharSequence suffix) { - if (hasEmpty(str, prefix, suffix) || - // 不包含起始字符串,则肯定没有子串 - false == contains(str, prefix)) { - return new String[0]; - } - - final List
- * 栗子: - * - *
- * StrUtil.subBetweenAll(null, *) = [] - * StrUtil.subBetweenAll(*, null) = [] - * StrUtil.subBetweenAll(*, *) = [] - * StrUtil.subBetweenAll("", "") = [] - * StrUtil.subBetweenAll("", "#") = [] - * StrUtil.subBetweenAll("gotanks", "") = [] - * StrUtil.subBetweenAll("#gotanks#", "#") = ["gotanks"] - * StrUtil.subBetweenAll("#hello# #world#!", "#") = ["hello", "world"] - * StrUtil.subBetweenAll("#hello# world#!", "#"); = ["hello"] - *- * - * @param str 被切割的字符串 - * @param prefixAndSuffix 截取开始和结束的字符串标识 - * @return 截取后的字符串 - * @author gotanks - * @since 5.5.0 - */ - public static String[] subBetweenAll(CharSequence str, CharSequence prefixAndSuffix) { - return subBetweenAll(str, prefixAndSuffix, prefixAndSuffix); - } - - /** - * 给定字符串是否被字符包围 - * - * @param str 字符串 - * @param prefix 前缀 - * @param suffix 后缀 - * @return 是否包围,空串不包围 - */ - public static boolean isSurround(CharSequence str, CharSequence prefix, CharSequence suffix) { - if (StrUtil.isBlank(str)) { - return false; - } - if (str.length() < (prefix.length() + suffix.length())) { - return false; - } - - final String str2 = str.toString(); - return str2.startsWith(prefix.toString()) && str2.endsWith(suffix.toString()); - } - - /** - * 给定字符串是否被字符包围 - * - * @param str 字符串 - * @param prefix 前缀 - * @param suffix 后缀 - * @return 是否包围,空串不包围 - */ - public static boolean isSurround(CharSequence str, char prefix, char suffix) { - if (StrUtil.isBlank(str)) { - return false; - } - if (str.length() < 2) { - return false; - } - - return str.charAt(0) == prefix && str.charAt(str.length() - 1) == suffix; - } - - /** - * 重复某个字符 - * - * @param c 被重复的字符 - * @param count 重复的数目,如果小于等于0则返回"" - * @return 重复字符字符串 - */ - public static String repeat(char c, int count) { - if (count <= 0) { - return EMPTY; - } - - char[] result = new char[count]; - for (int i = 0; i < count; i++) { - result[i] = c; - } - return new String(result); - } - - /** - * 重复某个字符串 - * - * @param str 被重复的字符 - * @param count 重复的数目 - * @return 重复字符字符串 - */ - public static String repeat(CharSequence str, int count) { - if (null == str) { - return null; - } - if (count <= 0 || str.length() == 0) { - return EMPTY; - } - if (count == 1) { - return str.toString(); - } - - // 检查 - final int len = str.length(); - final long longSize = (long) len * (long) count; - final int size = (int) longSize; - if (size != longSize) { - throw new ArrayIndexOutOfBoundsException("Required String length is too large: " + longSize); - } - - final char[] array = new char[size]; - str.toString().getChars(0, len, array, 0); - int n; - for (n = len; n < size - n; n <<= 1) {// n <<= 1相当于n *2 - System.arraycopy(array, 0, array, n, n); - } - System.arraycopy(array, 0, array, n, size - n); - return new String(array); - } - - /** - * 重复某个字符串到指定长度 - * - * @param str 被重复的字符 - * @param padLen 指定长度 - * @return 重复字符字符串 - * @since 4.3.2 - */ - public static String repeatByLength(CharSequence str, int padLen) { - if (null == str) { - return null; - } - if (padLen <= 0) { - return StrUtil.EMPTY; - } - final int strLen = str.length(); - if (strLen == padLen) { - return str.toString(); - } else if (strLen > padLen) { - return subPre(str, padLen); - } - - // 重复,直到达到指定长度 - final char[] padding = new char[padLen]; - for (int i = 0; i < padLen; i++) { - padding[i] = str.charAt(i % strLen); - } - return new String(padding); - } - - /** - * 重复某个字符串并通过分界符连接 - * - *
- * StrUtil.repeatAndJoin("?", 5, ",") = "?,?,?,?,?" - * StrUtil.repeatAndJoin("?", 0, ",") = "" - * StrUtil.repeatAndJoin("?", 5, null) = "?????" - *- * - * @param str 被重复的字符串 - * @param count 数量 - * @param conjunction 分界符 - * @return 连接后的字符串 - * @since 4.0.1 - */ - public static String repeatAndJoin(CharSequence str, int count, CharSequence conjunction) { - if (count <= 0) { - return EMPTY; - } - final StrBuilder builder = StrBuilder.create(); - boolean isFirst = true; - while (count-- > 0) { - if (isFirst) { - isFirst = false; - } else if (isNotEmpty(conjunction)) { - builder.append(conjunction); - } - builder.append(str); - } - return builder.toString(); - } - - /** - * 比较两个字符串(大小写敏感)。 - * - *
- * equals(null, null) = true - * equals(null, "abc") = false - * equals("abc", null) = false - * equals("abc", "abc") = true - * equals("abc", "ABC") = false - *- * - * @param str1 要比较的字符串1 - * @param str2 要比较的字符串2 - * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} - */ - public static boolean equals(CharSequence str1, CharSequence str2) { - return equals(str1, str2, false); - } - - /** - * 比较两个字符串(大小写不敏感)。 - * - *
- * equalsIgnoreCase(null, null) = true - * equalsIgnoreCase(null, "abc") = false - * equalsIgnoreCase("abc", null) = false - * equalsIgnoreCase("abc", "abc") = true - * equalsIgnoreCase("abc", "ABC") = true - *- * - * @param str1 要比较的字符串1 - * @param str2 要比较的字符串2 - * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} - */ - public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) { - return equals(str1, str2, true); - } - - /** - * 比较两个字符串是否相等。 - * - * @param str1 要比较的字符串1 - * @param str2 要比较的字符串2 - * @param ignoreCase 是否忽略大小写 - * @return 如果两个字符串相同,或者都是{@code null},则返回{@code true} - * @since 3.2.0 - */ - public static boolean equals(CharSequence str1, CharSequence str2, boolean ignoreCase) { - if (null == str1) { - // 只有两个都为null才判断相等 - return str2 == null; - } - if (null == str2) { - // 字符串2空,字符串1非空,直接false - return false; - } - - if (ignoreCase) { - return str1.toString().equalsIgnoreCase(str2.toString()); - } else { - return str1.toString().contentEquals(str2); - } - } - - /** - * 给定字符串是否与提供的中任一字符串相同(忽略大小写),相同则返回{@code true},没有相同的返回{@code false}
- * HelloWorld=》hello_world - * Hello_World=》hello_world - * HelloWorld_test=》hello_world_test - *- * - * @param str 转换前的驼峰式命名的字符串,也可以为下划线形式 - * @return 转换后下划线方式命名的字符串 - */ - public static String toUnderlineCase(CharSequence str) { - return toSymbolCase(str, CharUtil.UNDERLINE); - } - - /** - * 将驼峰式命名的字符串转换为使用符号连接方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
- * StrUtil.padPre(null, *, *);//null - * StrUtil.padPre("1", 3, "ABC");//"AB1" - * StrUtil.padPre("123", 2, "ABC");//"12" - *- * - * @param str 字符串 - * @param minLength 最小长度 - * @param padStr 补充的字符 - * @return 补充后的字符串 - */ - public static String padPre(CharSequence str, int minLength, CharSequence padStr) { - if (null == str) { - return null; - } - final int strLen = str.length(); - if (strLen == minLength) { - return str.toString(); - } else if (strLen > minLength) { - return subPre(str, minLength); - } - - return repeatByLength(padStr, minLength - strLen).concat(str.toString()); - } - - /** - * 补充字符串以满足最小长度 - * - *
- * StrUtil.padPre(null, *, *);//null - * StrUtil.padPre("1", 3, '0');//"001" - * StrUtil.padPre("123", 2, '0');//"12" - *- * - * @param str 字符串 - * @param minLength 最小长度 - * @param padChar 补充的字符 - * @return 补充后的字符串 - */ - public static String padPre(CharSequence str, int minLength, char padChar) { - if (null == str) { - return null; - } - final int strLen = str.length(); - if (strLen == minLength) { - return str.toString(); - } else if (strLen > minLength) { - return subPre(str, minLength); - } - - return repeat(padChar, minLength - strLen).concat(str.toString()); - } - - /** - * 补充字符串以满足最小长度 - * - *
- * StrUtil.padAfter(null, *, *);//null - * StrUtil.padAfter("1", 3, '0');//"100" - * StrUtil.padAfter("123", 2, '0');//"23" - *- * - * @param str 字符串,如果为{@code null},直接返回null - * @param minLength 最小长度 - * @param padChar 补充的字符 - * @return 补充后的字符串 - */ - public static String padAfter(CharSequence str, int minLength, char padChar) { - if (null == str) { - return null; - } - final int strLen = str.length(); - if (strLen == minLength) { - return str.toString(); - } else if (strLen > minLength) { - return sub(str, strLen - minLength, strLen); - } - - return str.toString().concat(repeat(padChar, minLength - strLen)); - } - - /** - * 补充字符串以满足最小长度 - * - *
- * StrUtil.padAfter(null, *, *);//null - * StrUtil.padAfter("1", 3, "ABC");//"1AB" - * StrUtil.padAfter("123", 2, "ABC");//"23" - *- * - * @param str 字符串,如果为{@code null},直接返回null - * @param minLength 最小长度 - * @param padStr 补充的字符 - * @return 补充后的字符串 - * @since 4.3.2 - */ - public static String padAfter(CharSequence str, int minLength, CharSequence padStr) { - if (null == str) { - return null; - } - final int strLen = str.length(); - if (strLen == minLength) { - return str.toString(); - } else if (strLen > minLength) { - return subSufByLength(str, minLength); - } - - return str.toString().concat(repeatByLength(padStr, minLength - strLen)); - } - - /** - * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 - * - *
- * StrUtil.center(null, *) = null - * StrUtil.center("", 4) = " " - * StrUtil.center("ab", -1) = "ab" - * StrUtil.center("ab", 4) = " ab " - * StrUtil.center("abcd", 2) = "abcd" - * StrUtil.center("a", 4) = " a " - *- * - * @param str 字符串 - * @param size 指定长度 - * @return 补充后的字符串 - * @since 4.3.2 - */ - public static String center(CharSequence str, final int size) { - return center(str, size, CharUtil.SPACE); - } - - /** - * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 - * - *
- * StrUtil.center(null, *, *) = null - * StrUtil.center("", 4, ' ') = " " - * StrUtil.center("ab", -1, ' ') = "ab" - * StrUtil.center("ab", 4, ' ') = " ab " - * StrUtil.center("abcd", 2, ' ') = "abcd" - * StrUtil.center("a", 4, ' ') = " a " - * StrUtil.center("a", 4, 'y') = "yayy" - * StrUtil.center("abc", 7, ' ') = " abc " - *- * - * @param str 字符串 - * @param size 指定长度 - * @param padChar 两边补充的字符 - * @return 补充后的字符串 - * @since 4.3.2 - */ - public static String center(CharSequence str, final int size, char padChar) { - if (str == null || size <= 0) { - return str(str); - } - final int strLen = str.length(); - final int pads = size - strLen; - if (pads <= 0) { - return str.toString(); - } - str = padPre(str, strLen + pads / 2, padChar); - str = padAfter(str, size, padChar); - return str.toString(); - } - - /** - * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 - * - *
- * StrUtil.center(null, *, *) = null - * StrUtil.center("", 4, " ") = " " - * StrUtil.center("ab", -1, " ") = "ab" - * StrUtil.center("ab", 4, " ") = " ab " - * StrUtil.center("abcd", 2, " ") = "abcd" - * StrUtil.center("a", 4, " ") = " a " - * StrUtil.center("a", 4, "yz") = "yayz" - * StrUtil.center("abc", 7, null) = " abc " - * StrUtil.center("abc", 7, "") = " abc " - *- * - * @param str 字符串 - * @param size 指定长度 - * @param padStr 两边补充的字符串 - * @return 补充后的字符串 - */ - public static String center(CharSequence str, final int size, CharSequence padStr) { - if (str == null || size <= 0) { - return str(str); - } - if (isEmpty(padStr)) { - padStr = SPACE; - } - final int strLen = str.length(); - final int pads = size - strLen; - if (pads <= 0) { - return str.toString(); - } - str = padPre(str, strLen + pads / 2, padStr); - str = padAfter(str, size, padStr); - return str.toString(); - } - /** * 创建StringBuilder对象 * @@ -3609,30 +507,6 @@ public class StrUtil { return StrBuilder.create(capacity); } - /** - * 创建StringBuilder对象 - * - * @param strs 初始字符串列表 - * @return StringBuilder对象 - */ - public static StringBuilder builder(CharSequence... strs) { - final StringBuilder sb = new StringBuilder(); - for (CharSequence str : strs) { - sb.append(str); - } - return sb; - } - - /** - * 创建StrBuilder对象 - * - * @param strs 初始字符串列表 - * @return StrBuilder对象 - */ - public static StrBuilder strBuilder(CharSequence... strs) { - return StrBuilder.create(strs); - } - /** * 获得StringReader * @@ -3655,566 +529,6 @@ public class StrUtil { return new StringWriter(); } - /** - * 统计指定内容中包含指定字符串的数量
- * StrUtil.count(null, *) = 0 - * StrUtil.count("", *) = 0 - * StrUtil.count("abba", null) = 0 - * StrUtil.count("abba", "") = 0 - * StrUtil.count("abba", "a") = 2 - * StrUtil.count("abba", "ab") = 1 - * StrUtil.count("abba", "xxx") = 0 - *- * - * @param content 被查找的字符串 - * @param strForSearch 需要查找的字符串 - * @return 查找到的个数 - */ - public static int count(CharSequence content, CharSequence strForSearch) { - if (hasEmpty(content, strForSearch) || strForSearch.length() > content.length()) { - return 0; - } - - int count = 0; - int idx = 0; - final String content2 = content.toString(); - final String strForSearch2 = strForSearch.toString(); - while ((idx = content2.indexOf(strForSearch2, idx)) > -1) { - count++; - idx += strForSearch.length(); - } - return count; - } - - /** - * 统计指定内容中包含指定字符的数量 - * - * @param content 内容 - * @param charForSearch 被统计的字符 - * @return 包含数量 - */ - public static int count(CharSequence content, char charForSearch) { - int count = 0; - if (isEmpty(content)) { - return 0; - } - int contentLength = content.length(); - for (int i = 0; i < contentLength; i++) { - if (charForSearch == content.charAt(i)) { - count++; - } - } - return count; - } - - /** - * 将字符串切分为N等份 - * - * @param str 字符串 - * @param partLength 每等份的长度 - * @return 切分后的数组 - * @since 3.0.6 - */ - public static String[] cut(CharSequence str, int partLength) { - if (null == str) { - return null; - } - int len = str.length(); - if (len < partLength) { - return new String[]{str.toString()}; - } - int part = NumberUtil.count(len, partLength); - final String[] array = new String[part]; - - final String str2 = str.toString(); - for (int i = 0; i < part; i++) { - array[i] = str2.substring(i * partLength, (i == part - 1) ? len : (partLength + i * partLength)); - } - return array; - } - - /** - * 将给定字符串,变成 "xxx...xxx" 形式的字符串 - * - * @param str 字符串 - * @param maxLength 最大长度 - * @return 截取后的字符串 - */ - public static String brief(CharSequence str, int maxLength) { - if (null == str) { - return null; - } - if (str.length() <= maxLength) { - return str.toString(); - } - int w = maxLength / 2; - int l = str.length() + 3; - - final String str2 = str.toString(); - return format("{}...{}", str2.substring(0, maxLength - w), str2.substring(l - w)); - } - - /** - * 比较两个字符串,用于排序 - * - *
- * StrUtil.compare(null, null, *) = 0 - * StrUtil.compare(null , "a", true) < 0 - * StrUtil.compare(null , "a", false) > 0 - * StrUtil.compare("a", null, true) > 0 - * StrUtil.compare("a", null, false) < 0 - * StrUtil.compare("abc", "abc", *) = 0 - * StrUtil.compare("a", "b", *) < 0 - * StrUtil.compare("b", "a", *) > 0 - * StrUtil.compare("a", "B", *) > 0 - * StrUtil.compare("ab", "abc", *) < 0 - *- * - * @param str1 字符串1 - * @param str2 字符串2 - * @param nullIsLess {@code null} 值是否排在前(null是否小于非空值) - * @return 排序值。负数:str1 < str2,正数:str1 > str2, 0:str1 == str2 - */ - public static int compare(final CharSequence str1, final CharSequence str2, final boolean nullIsLess) { - if (str1 == str2) { - return 0; - } - if (str1 == null) { - return nullIsLess ? -1 : 1; - } - if (str2 == null) { - return nullIsLess ? 1 : -1; - } - return str1.toString().compareTo(str2.toString()); - } - - /** - * 比较两个字符串,用于排序,大小写不敏感 - * - *
- * StrUtil.compareIgnoreCase(null, null, *) = 0 - * StrUtil.compareIgnoreCase(null , "a", true) < 0 - * StrUtil.compareIgnoreCase(null , "a", false) > 0 - * StrUtil.compareIgnoreCase("a", null, true) > 0 - * StrUtil.compareIgnoreCase("a", null, false) < 0 - * StrUtil.compareIgnoreCase("abc", "abc", *) = 0 - * StrUtil.compareIgnoreCase("abc", "ABC", *) = 0 - * StrUtil.compareIgnoreCase("a", "b", *) < 0 - * StrUtil.compareIgnoreCase("b", "a", *) > 0 - * StrUtil.compareIgnoreCase("a", "B", *) < 0 - * StrUtil.compareIgnoreCase("A", "b", *) < 0 - * StrUtil.compareIgnoreCase("ab", "abc", *) < 0 - *- * - * @param str1 字符串1 - * @param str2 字符串2 - * @param nullIsLess {@code null} 值是否排在前(null是否小于非空值) - * @return 排序值。负数:str1 < str2,正数:str1 > str2, 0:str1 == str2 - */ - public static int compareIgnoreCase(CharSequence str1, CharSequence str2, boolean nullIsLess) { - if (str1 == str2) { - return 0; - } - if (str1 == null) { - return nullIsLess ? -1 : 1; - } - if (str2 == null) { - return nullIsLess ? 1 : -1; - } - return str1.toString().compareToIgnoreCase(str2.toString()); - } - - /** - * 比较两个版本
- * StrUtil.compareVersion(null, "v1") < 0 - * StrUtil.compareVersion("v1", "v1") = 0 - * StrUtil.compareVersion(null, null) = 0 - * StrUtil.compareVersion("v1", null) > 0 - * StrUtil.compareVersion("1.0.0", "1.0.2") < 0 - * StrUtil.compareVersion("1.0.2", "1.0.2a") < 0 - * StrUtil.compareVersion("1.13.0", "1.12.1c") > 0 - * StrUtil.compareVersion("V0.0.20170102", "V0.0.20170101") > 0 - *- * - * @param version1 版本1 - * @param version2 版本2 - * @return 排序值。负数:version1 < version2,正数:version1 > version2, 0:version1 == version2 - * @since 4.0.2 - */ - public static int compareVersion(CharSequence version1, CharSequence version2) { - return VersionComparator.INSTANCE.compare(str(version1), str(version2)); - } - - /** - * 指定范围内查找指定字符 - * - * @param str 字符串 - * @param searchChar 被查找的字符 - * @return 位置 - */ - public static int indexOf(final CharSequence str, char searchChar) { - return indexOf(str, searchChar, 0); - } - - /** - * 指定范围内查找指定字符 - * - * @param str 字符串 - * @param searchChar 被查找的字符 - * @param start 起始位置,如果小于0,从0开始查找 - * @return 位置 - */ - public static int indexOf(CharSequence str, char searchChar, int start) { - if (str instanceof String) { - return ((String) str).indexOf(searchChar, start); - } else { - return indexOf(str, searchChar, start, -1); - } - } - - /** - * 指定范围内查找指定字符 - * - * @param str 字符串 - * @param searchChar 被查找的字符 - * @param start 起始位置,如果小于0,从0开始查找 - * @param end 终止位置,如果超过str.length()则默认查找到字符串末尾 - * @return 位置 - */ - public static int indexOf(final CharSequence str, char searchChar, int start, int end) { - if (isEmpty(str)) { - return INDEX_NOT_FOUND; - } - final int len = str.length(); - if (start < 0 || start > len) { - start = 0; - } - if (end > len || end < 0) { - end = len; - } - for (int i = start; i < end; i++) { - if (str.charAt(i) == searchChar) { - return i; - } - } - return INDEX_NOT_FOUND; - } - - /** - * 指定范围内查找字符串,忽略大小写
- * StrUtil.indexOfIgnoreCase(null, *, *) = -1 - * StrUtil.indexOfIgnoreCase(*, null, *) = -1 - * StrUtil.indexOfIgnoreCase("", "", 0) = 0 - * StrUtil.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 - * StrUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 - * StrUtil.indexOfIgnoreCase("aabaabaa", "", 2) = 2 - * StrUtil.indexOfIgnoreCase("abc", "", 9) = -1 - *- * - * @param str 字符串 - * @param searchStr 需要查找位置的字符串 - * @return 位置 - * @since 3.2.1 - */ - public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { - return indexOfIgnoreCase(str, searchStr, 0); - } - - /** - * 指定范围内查找字符串 - * - *
- * StrUtil.indexOfIgnoreCase(null, *, *) = -1 - * StrUtil.indexOfIgnoreCase(*, null, *) = -1 - * StrUtil.indexOfIgnoreCase("", "", 0) = 0 - * StrUtil.indexOfIgnoreCase("aabaabaa", "A", 0) = 0 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 0) = 2 - * StrUtil.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 3) = 5 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", 9) = -1 - * StrUtil.indexOfIgnoreCase("aabaabaa", "B", -1) = 2 - * StrUtil.indexOfIgnoreCase("aabaabaa", "", 2) = 2 - * StrUtil.indexOfIgnoreCase("abc", "", 9) = -1 - *- * - * @param str 字符串 - * @param searchStr 需要查找位置的字符串 - * @param fromIndex 起始位置 - * @return 位置 - * @since 3.2.1 - */ - public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) { - return indexOf(str, searchStr, fromIndex, true); - } - - /** - * 指定范围内查找字符串 - * - * @param str 字符串 - * @param searchStr 需要查找位置的字符串 - * @param fromIndex 起始位置 - * @param ignoreCase 是否忽略大小写 - * @return 位置 - * @since 3.2.1 - */ - public static int indexOf(final CharSequence str, CharSequence searchStr, int fromIndex, boolean ignoreCase) { - if (str == null || searchStr == null) { - return INDEX_NOT_FOUND; - } - if (fromIndex < 0) { - fromIndex = 0; - } - - final int endLimit = str.length() - searchStr.length() + 1; - if (fromIndex > endLimit) { - return INDEX_NOT_FOUND; - } - if (searchStr.length() == 0) { - return fromIndex; - } - - if (false == ignoreCase) { - // 不忽略大小写调用JDK方法 - return str.toString().indexOf(searchStr.toString(), fromIndex); - } - - for (int i = fromIndex; i < endLimit; i++) { - if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) { - return i; - } - } - return INDEX_NOT_FOUND; - } - - /** - * 指定范围内查找字符串,忽略大小写 - * - * @param str 字符串 - * @param searchStr 需要查找位置的字符串 - * @return 位置 - * @since 3.2.1 - */ - public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) { - return lastIndexOfIgnoreCase(str, searchStr, str.length()); - } - - /** - * 指定范围内查找字符串,忽略大小写
- * 如果 str=null 或 searchStr=null 或 ordinal≥0 则返回-1
- * 此方法来自:Apache-Commons-Lang
- *
- * 例子(*代表任意字符): - * - *
- * StrUtil.ordinalIndexOf(null, *, *) = -1 - * StrUtil.ordinalIndexOf(*, null, *) = -1 - * StrUtil.ordinalIndexOf("", "", *) = 0 - * StrUtil.ordinalIndexOf("aabaabaa", "a", 1) = 0 - * StrUtil.ordinalIndexOf("aabaabaa", "a", 2) = 1 - * StrUtil.ordinalIndexOf("aabaabaa", "b", 1) = 2 - * StrUtil.ordinalIndexOf("aabaabaa", "b", 2) = 5 - * StrUtil.ordinalIndexOf("aabaabaa", "ab", 1) = 1 - * StrUtil.ordinalIndexOf("aabaabaa", "ab", 2) = 4 - * StrUtil.ordinalIndexOf("aabaabaa", "", 1) = 0 - * StrUtil.ordinalIndexOf("aabaabaa", "", 2) = 0 - *- * - * @param str 被检查的字符串,可以为null - * @param searchStr 被查找的字符串,可以为null - * @param ordinal 第几次出现的位置 - * @return 查找到的位置 - * @since 3.2.3 - */ - public static int ordinalIndexOf(String str, String searchStr, int ordinal) { - if (str == null || searchStr == null || ordinal <= 0) { - return INDEX_NOT_FOUND; - } - if (searchStr.length() == 0) { - return 0; - } - int found = 0; - int index = INDEX_NOT_FOUND; - do { - index = str.indexOf(searchStr, index + 1); - if (index < 0) { - return index; - } - found++; - } while (found < ordinal); - return index; - } - - // ------------------------------------------------------------------------------------------------------------------ Append and prepend - - /** - * 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串
- * 1. 大写字母包括A-Z - * 2. 其它非字母的Unicode符都算作大写 - *- * - * @param str 被检查的字符串 - * @return 是否全部为大写 - * @since 4.2.2 + * @param template 文本模板,被替换的部分用 {key} 表示 + * @param map 参数值对 + * @param ignoreNull 是否忽略 {@code null} 值,忽略则 {@code null} 值对应的变量不被替换,否则替换为"" + * @return 格式化后的文本 + * @since 5.4.3 */ - public static boolean isUpperCase(CharSequence str) { - if (null == str) { - return false; + public static String format(CharSequence template, Map, ?> map, boolean ignoreNull) { + if (null == template) { + return null; } - final int len = str.length(); - for (int i = 0; i < len; i++) { - if (Character.isLowerCase(str.charAt(i))) { - return false; + if (null == map || map.isEmpty()) { + return template.toString(); + } + + String template2 = template.toString(); + String value; + for (Map.Entry, ?> entry : map.entrySet()) { + value = utf8Str(entry.getValue()); + if (null == value && ignoreNull) { + continue; } + template2 = replace(template2, "{" + entry.getKey() + "}", value); } - return true; - } - - /** - * 给定字符串中的字母是否全部为小写,判断依据如下: - * - *
- * 1. 小写字母包括a-z - * 2. 其它非字母的Unicode符都算作小写 - *- * - * @param str 被检查的字符串 - * @return 是否全部为小写 - * @since 4.2.2 - */ - public static boolean isLowerCase(CharSequence str) { - if (null == str) { - return false; - } - final int len = str.length(); - for (int i = 0; i < len; i++) { - if (Character.isUpperCase(str.charAt(i))) { - return false; - } - } - return true; - } - - /** - * 获取字符串的长度,如果为null返回0 - * - * @param cs a 字符串 - * @return 字符串的长度,如果为null返回0 - * @since 4.3.2 - */ - public static int length(CharSequence cs) { - return cs == null ? 0 : cs.length(); - } - - /** - * 给定字符串转为bytes后的byte数(byte长度) - * - * @param cs 字符串 - * @param charset 编码 - * @return byte长度 - * @since 4.5.2 - */ - public static int byteLength(CharSequence cs, Charset charset) { - return cs == null ? 0 : cs.toString().getBytes(charset).length; - } - - /** - * 切换给定字符串中的大小写。大写转小写,小写转大写。 - * - *
- * StrUtil.swapCase(null) = null - * StrUtil.swapCase("") = "" - * StrUtil.swapCase("The dog has a BONE") = "tHE DOG HAS A bone" - *- * - * @param str 字符串 - * @return 交换后的字符串 - * @since 4.3.2 - */ - public static String swapCase(final String str) { - if (isEmpty(str)) { - return str; - } - - final char[] buffer = str.toCharArray(); - - for (int i = 0; i < buffer.length; i++) { - final char ch = buffer[i]; - if (Character.isUpperCase(ch)) { - buffer[i] = Character.toLowerCase(ch); - } else if (Character.isTitleCase(ch)) { - buffer[i] = Character.toLowerCase(ch); - } else if (Character.isLowerCase(ch)) { - buffer[i] = Character.toUpperCase(ch); - } - } - return new String(buffer); - } - - /** - * 过滤字符串 - * - * @param str 字符串 - * @param filter 过滤器 - * @return 过滤后的字符串 - * @since 5.4.0 - */ - public static String filter(CharSequence str, final Filter