com.litongjava.tio.utils.hutool.StrUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tio-utils Show documentation
Show all versions of tio-utils Show documentation
t-io is a aio framework for java
package com.litongjava.tio.utils.hutool;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.Date;
public class StrUtil {
public static final int INDEX_NOT_FOUND = -1;
public static final String EMPTY = "";
private static int cacheSize = 2048;
private static String[] caches = new String[cacheSize];
static {
for (int i = 0; i < cacheSize; i++) {
caches[i] = String.valueOf(i);
}
}
/**
* 用缓存将int转成str
*
* @param data
* @return
*/
public static String int2Str(int data) {
if (data < cacheSize) {
return caches[data];
} else {
return String.valueOf(data);
}
}
/**
* 去除字符串两边空白符,传入null也返回null
*
* @param value 值
* @return 去除空白符的值
*/
public static String trim(String value) {
return (null == value) ? null : value.trim();
}
/**
* 字符串是否为空,空的定义如下:
* 1、为null
* 2、为""
*
* @param str 被检测的字符串
* @return 是否为空
*/
public static boolean isEmpty(CharSequence str) {
return str == null || str.length() == 0;
}
/**
* 字符串是否为非空白 空白的定义如下:
* 1、不为null
* 2、不为不可见字符(如空格)
* 3、不为""
*
* @param str 被检测的字符串
* @return 是否为非空
*/
public static boolean isNotBlank(CharSequence str) {
return false == isBlank(str);
}
public static boolean notBlank(CharSequence str) {
return false == isBlank(str);
}
/**
* 字符串是否为空白 空白的定义如下:
* 1、为null
* 2、为不可见字符(如空格)
* 3、""
*
* @param str 被检测的字符串
* @return 是否为空
*/
public static boolean isBlank(CharSequence str) {
int length;
if ((str == null) || ((length = str.length()) == 0)) {
return true;
}
for (int i = 0; i < length; i++) {
// 只要有一个非空字符即为非空字符串
if (false == isBlankChar(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* 数组或集合转String
*
* @param obj 集合或数组对象
* @return 数组字符串,与集合转字符串格式相同
*/
public static String arrayToString(Object obj) {
if (null == obj) {
return null;
}
if (isArray(obj)) {
try {
return Arrays.deepToString((Object[]) obj);
} catch (Exception e) {
final String className = obj.getClass().getComponentType().getName();
switch (className) {
case "long":
return Arrays.toString((long[]) obj);
case "int":
return Arrays.toString((int[]) obj);
case "short":
return Arrays.toString((short[]) obj);
case "char":
return Arrays.toString((char[]) obj);
case "byte":
return Arrays.toString((byte[]) obj);
case "boolean":
return Arrays.toString((boolean[]) obj);
case "float":
return Arrays.toString((float[]) obj);
case "double":
return Arrays.toString((double[]) obj);
default:
throw new RuntimeException(e);
}
}
}
return obj.toString();
}
/**
* 是否以指定字符串开头,忽略大小写
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @return 是否以指定字符串开头
*/
public static boolean startWithIgnoreCase(CharSequence str, CharSequence prefix) {
return startWith(str, prefix, true);
}
/**
* 是否以指定字符串开头
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @param isIgnoreCase 是否忽略大小写
* @return 是否以指定字符串开头
*/
public static boolean startWith(CharSequence str, CharSequence prefix, boolean isIgnoreCase) {
if (null == str || null == prefix) {
if (null == str && null == prefix) {
return true;
}
return false;
}
if (isIgnoreCase) {
return str.toString().toLowerCase().startsWith(prefix.toString().toLowerCase());
} else {
return str.toString().startsWith(prefix.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 如果两个字符串相同,或者都是null
,则返回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 如果两个字符串相同,或者都是null
,则返回true
*/
public static boolean equalsIgnoreCase(CharSequence str1, CharSequence str2) {
return equals(str1, str2, true);
}
/**
* 比较两个字符串是否相等。
*
* @param str1 要比较的字符串1
* @param str2 要比较的字符串2
* @param ignoreCase 是否忽略大小写
* @return 如果两个字符串相同,或者都是null
,则返回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.equals(str2);
}
}
/**
* 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串
* 字符填充于字符串后
*
* @param str 被填充的字符串
* @param filledChar 填充的字符
* @param len 填充长度
* @return 填充后的字符串
* @since 3.1.2
*/
public static String fillAfter(String str, char filledChar, int len) {
return fill(str, filledChar, len, false);
}
/**
* 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串
*
* @param str 被填充的字符串
* @param filledChar 填充的字符
* @param len 填充长度
* @param isPre 是否填充在前
* @return 填充后的字符串
* @since 3.1.2
*/
public static String fill(String str, char filledChar, int len, boolean isPre) {
final int strLen = str.length();
if (strLen > len) {
return str;
}
String filledStr = repeat(filledChar, len - strLen);
return isPre ? filledStr.concat(str) : str.concat(filledStr);
}
/**
* 重复某个字符
*
* @param c 被重复的字符
* @param count 重复的数目,如果小于等于0则返回""
* @return 重复字符字符串
*/
public static String repeat(char c, int count) {
if (count <= 0) {
return "";
}
char[] result = new char[count];
for (int i = 0; i < count; i++) {
result[i] = c;
}
return new String(result);
}
/**
* 除去字符串头部的空白,如果字符串是null
,则返回null
。
*
*
* 注意,和String.trim
不同,此方法使用CharUtil.isBlankChar
来判定空白,
* 因而可以除去英文字符集之外的其它空白,如中文空格。
*
*
* trimStart(null) = null
* trimStart("") = ""
* trimStart("abc") = "abc"
* trimStart(" abc") = "abc"
* trimStart("abc ") = "abc "
* trimStart(" abc ") = "abc "
*
*
* @param str 要处理的字符串
*
* @return 除去空白的字符串,如果原字串为null
或结果字符串为""
,则返回
* null
*/
public static String trimStart(CharSequence str) {
return trim(str, -1);
}
/**
* 除去字符串尾部的空白,如果字符串是null
,则返回null
。
*
*
* 注意,和String.trim
不同,此方法使用CharUtil.isBlankChar
来判定空白,
* 因而可以除去英文字符集之外的其它空白,如中文空格。
*
*
* trimEnd(null) = null
* trimEnd("") = ""
* trimEnd("abc") = "abc"
* trimEnd(" abc") = " abc"
* trimEnd("abc ") = "abc"
* trimEnd(" abc ") = " abc"
*
*
* @param str 要处理的字符串
*
* @return 除去空白的字符串,如果原字串为null
或结果字符串为""
,则返回
* null
*/
public static String trimEnd(CharSequence str) {
return trim(str, 1);
}
/**
* 除去字符串头尾部的空白符,如果字符串是null
,依然返回null
。
*
* @param str 要处理的字符串
* @param mode -1
表示trimStart,0
表示trim全部,
* 1
表示trimEnd
*
* @return 除去指定字符后的的字符串,如果原字串为null
,则返回null
*/
private static String trim(CharSequence str, int mode) {
if (str == null) {
return null;
}
int length = str.length();
int start = 0;
int end = length;
// 扫描字符串头部
if (mode <= 0) {
while ((start < end) && (isBlankChar(str.charAt(start)))) {
start++;
}
}
// 扫描字符串尾部
if (mode >= 0) {
while ((start < end) && (isBlankChar(str.charAt(end - 1)))) {
end--;
}
}
if ((start > 0) || (end < length)) {
return str.toString().substring(start, end);
}
return str.toString();
}
/**
* 对象是否为数组对象
*
* @param obj 对象
* @return 是否为数组对象,如果为{@code null} 返回false
*/
private static boolean isArray(Object obj) {
if (null == obj) {
// throw new NullPointerException("Object check for isArray is null");
return false;
}
return obj.getClass().isArray();
}
/**
* 是否空白符
* 空白符包括空格、制表符、全角空格和不间断空格
*
* @see Character#isWhitespace(int)
* @see Character#isSpaceChar(int)
* @param c 字符
* @return 是否空白符
* @since 4.0.10
*/
private static boolean isBlankChar(char c) {
return Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\ufeff' || c == '\u202a';
}
/**
* 指定范围内查找指定字符
*
* @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(final 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) {
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 -1;
}
/**
* 指定范围内查找字符串,忽略大小写
*
*
* 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());
}
/**
* 指定范围内查找字符串,忽略大小写
*
* @param str 字符串
* @param searchStr 需要查找位置的字符串
* @param fromIndex 起始位置,从后往前计数
* @return 位置
* @since 3.2.1
*/
public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int fromIndex) {
return lastIndexOf(str, searchStr, fromIndex, true);
}
/**
* 指定范围内查找字符串
*
* @param str 字符串
* @param searchStr 需要查找位置的字符串
* @param fromIndex 起始位置,从后往前计数
* @param ignoreCase 是否忽略大小写
* @return 位置
* @since 3.2.1
*/
public static int lastIndexOf(final CharSequence str, final CharSequence searchStr, int fromIndex, boolean ignoreCase) {
if (str == null || searchStr == null) {
return INDEX_NOT_FOUND;
}
if (fromIndex < 0) {
fromIndex = 0;
}
fromIndex = Math.min(fromIndex, str.length());
if (searchStr.length() == 0) {
return fromIndex;
}
if (false == ignoreCase) {
// 不忽略大小写调用JDK方法
return str.toString().lastIndexOf(searchStr.toString(), fromIndex);
}
for (int i = fromIndex; i > 0; i--) {
if (isSubEquals(str, i, searchStr, 0, searchStr.length(), true)) {
return i;
}
}
return INDEX_NOT_FOUND;
}
/**
* 截取两个字符串的不同部分(长度一致),判断截取的子串是否相同
* 任意一个字符串为null返回false
*
* @param str1 第一个字符串
* @param start1 第一个字符串开始的位置
* @param str2 第二个字符串
* @param start2 第二个字符串开始的位置
* @param length 截取长度
* @param ignoreCase 是否忽略大小写
* @return 子串是否相同
* @since 3.2.1
*/
public static boolean isSubEquals(CharSequence str1, int start1, CharSequence str2, int start2, int length, boolean ignoreCase) {
if (null == str1 || null == str2) {
return false;
}
return str1.toString().regionMatches(ignoreCase, start1, str2.toString(), start2, length);
}
/**
* 字符串是否以给定字符开始
*
* @param str 字符串
* @param c 字符
* @return 是否开始
*/
public static boolean startWith(CharSequence str, char c) {
return c == str.charAt(0);
}
/**
* 是否以指定字符串开头
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @return 是否以指定字符串开头
*/
public static boolean startWith(CharSequence str, CharSequence prefix) {
return startWith(str, prefix, false);
}
/**
* 字符串是否以给定字符结尾
*
* @param str 字符串
* @param c 字符
* @return 是否结尾
*/
public static boolean endWith(CharSequence str, char c) {
return c == str.charAt(str.length() - 1);
}
/**
* 是否以指定字符串结尾
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @param isIgnoreCase 是否忽略大小写
* @return 是否以指定字符串结尾
*/
public static boolean endWith(CharSequence str, CharSequence suffix, boolean isIgnoreCase) {
if (null == str || null == suffix) {
if (null == str && null == suffix) {
return true;
}
return false;
}
if (isIgnoreCase) {
return str.toString().toLowerCase().endsWith(suffix.toString().toLowerCase());
} else {
return str.toString().endsWith(suffix.toString());
}
}
/**
* 是否以指定字符串结尾
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @return 是否以指定字符串结尾
*/
public static boolean endWith(CharSequence str, CharSequence suffix) {
return endWith(str, suffix, false);
}
/**
* 是否以指定字符串结尾,忽略大小写
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @return 是否以指定字符串结尾
*/
public static boolean endWithIgnoreCase(CharSequence str, CharSequence suffix) {
return endWith(str, suffix, true);
}
/**
* 指定字符是否在字符串中出现过
*
* @param str 字符串
* @param searchChar 被查找的字符
* @return 是否包含
* @since 3.1.2
*/
public static boolean contains(CharSequence str, char searchChar) {
return indexOf(str, searchChar) > -1;
}
/**
* 是否包含特定字符,忽略大小写,如果给定两个参数都为null
,返回true
*
* @param str 被检测字符串
* @param testStr 被测试是否包含的字符串
* @return 是否包含
*/
public static boolean containsIgnoreCase(CharSequence str, CharSequence testStr) {
if (null == str) {
// 如果被监测字符串和
return null == testStr;
}
return str.toString().toLowerCase().contains(testStr.toString().toLowerCase());
}
/**
* @param str
* @param separator
* @return
* @author tanyaowu
*/
public static String[] split(String str, String separator) {
if (str == null) {
return null;
}
return str.split(separator);
}
/**
* 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj) {
return str(obj, StandardCharsets.UTF_8);
}
/**
* 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charsetName 字符集
* @return 字符串
*/
public static String str(Object obj, String charsetName) {
return str(obj, Charset.forName(charsetName));
}
/**
* 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @param charset 字符集
* @return 字符串
*/
public static String str(Object obj, Charset charset) {
if (null == obj) {
return null;
}
if (obj instanceof String) {
return (String) obj;
} else if (obj instanceof byte[]) {
return str((byte[]) obj, charset);
} else if (obj instanceof Byte[]) {
return str((Byte[]) obj, charset);
} else if (obj instanceof ByteBuffer) {
return str((ByteBuffer) obj, charset);
} else if (ArrayUtil.isArray(obj)) {
return ArrayUtil.toString(obj);
}
return obj.toString();
}
/**
* {@link CharSequence} 转为字符串,null安全
*
* @param cs {@link CharSequence}
* @return 字符串
*/
public static String str(CharSequence cs) {
return null == cs ? null : cs.toString();
}
/**
* 改进JDK subString
* index从0开始计算,最后一个字符为-1
* 如果from和to位置一样,返回 ""
* 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length
* 如果经过修正的index中from大于to,则互换from和to example:
* abcdefgh 2 3 =》 c
* abcdefgh 2 -3 =》 cde
*
* @param str String
* @param fromIndex 开始的index(包括)
* @param toIndex 结束的index(不包括)
* @return 字串
*/
public static String sub(CharSequence str, int fromIndex, int toIndex) {
if (isEmpty(str)) {
return str(str);
}
int len = str.length();
if (fromIndex < 0) {
fromIndex = len + fromIndex;
if (fromIndex < 0) {
fromIndex = 0;
}
} else if (fromIndex > len) {
fromIndex = len;
}
if (toIndex < 0) {
toIndex = len + toIndex;
if (toIndex < 0) {
toIndex = len;
}
} else if (toIndex > len) {
toIndex = len;
}
if (toIndex < fromIndex) {
int tmp = fromIndex;
fromIndex = toIndex;
toIndex = tmp;
}
if (fromIndex == toIndex) {
return EMPTY;
}
return str.toString().substring(fromIndex, toIndex);
}
/**
* 截取部分字符串,这里一个汉字的长度认为是2
*
* @param str 字符串
* @param len 切割的位置
* @param suffix 切割后加上后缀
* @return 切割后的字符串
* @since 3.1.1
*/
public static String subPreGbk(CharSequence str, int len, CharSequence suffix) {
if (isEmpty(str)) {
return str(str);
}
byte b[];
int counterOfDoubleByte = 0;
b = str.toString().getBytes(Charset.forName("GBK"));
if (b.length <= len) {
return str.toString();
}
for (int i = 0; i < len; i++) {
if (b[i] < 0) {
counterOfDoubleByte++;
}
}
if (counterOfDoubleByte % 2 != 0) {
len += 1;
}
return new String(b, 0, len, Charset.forName("GBK")) + suffix;
}
/**
* 限制字符串长度,如果超过指定长度,截取指定长度并在末尾加"..."
*
* @param string 字符串
* @param length 最大长度
* @return 切割后的剩余的前半部分字符串+"..."
* @since 4.0.10
*/
public static String maxLength(CharSequence string, int length) {
if (null == string) {
return null;
}
if (string.length() <= length) {
return string.toString();
}
return sub(string, 0, length) + "...";
}
/**
* 切割指定位置之前部分的字符串
*
* @param string 字符串
* @param toIndex 切割到的位置(不包括)
* @return 切割后的剩余的前半部分字符串
*/
public static String subPre(CharSequence string, int toIndex) {
return sub(string, 0, toIndex);
}
/**
* 切割指定位置之后部分的字符串
*
* @param string 字符串
* @param fromIndex 切割开始的位置(包括)
* @return 切割后后剩余的后半部分字符串
*/
public static String subSuf(CharSequence string, int fromIndex) {
if (isEmpty(string)) {
return null;
}
return sub(string, fromIndex, string.length());
}
/**
* 切割指定长度的后部分的字符串
*
*
* 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());
}
/**
* 截取字符串,从指定位置开始,截取指定长度的字符串
* author weibaohui
*
* @param input 原始字符串
* @param fromIndex 开始的index,包括
* @param length 要截取的长度
* @return 截取后的字符串
*/
public static String subWithLength(String input, int fromIndex, int length) {
return sub(input, fromIndex, fromIndex + length);
}
/**
* 截取分隔字符串之前的字符串,不包括分隔字符串
* 如果给定的字符串为空串(null或"")或者分隔字符串为null,返回原字符串
* 如果分隔字符串为空串"",则返回空串,如果分隔字符串未找到,返回原字符串
*
* 栗子:
*
*
* StrUtil.subBefore(null, *) = null
* StrUtil.subBefore("", *) = ""
* StrUtil.subBefore("abc", "a") = ""
* StrUtil.subBefore("abcba", "b") = "a"
* StrUtil.subBefore("abc", "c") = "ab"
* StrUtil.subBefore("abc", "d") = "abc"
* StrUtil.subBefore("abc", "") = ""
* StrUtil.subBefore("abc", null) = "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 (pos == INDEX_NOT_FOUND) {
return str;
}
return str.substring(0, pos);
}
/**
* 截取分隔字符串之后的字符串,不包括分隔字符串
* 如果给定的字符串为空串(null或""),返回原字符串
* 如果分隔字符串为空串(null或""),则返回空串,如果分隔字符串未找到,返回空串
*
* 栗子:
*
*
* StrUtil.subAfter(null, *) = null
* StrUtil.subAfter("", *) = ""
* StrUtil.subAfter(*, null) = ""
* StrUtil.subAfter("abc", "a") = "bc"
* StrUtil.subAfter("abcba", "b") = "cba"
* StrUtil.subAfter("abc", "c") = ""
* StrUtil.subAfter("abc", "d") = ""
* StrUtil.subAfter("abc", "") = "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 : string.toString();
}
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 (pos == INDEX_NOT_FOUND) {
return EMPTY;
}
return str.substring(pos + separator.length());
}
/**
* 截取指定字符串中间部分,不包括标识字符串
*
* 栗子:
*
*
* 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);
}
/**
*
* @param type
* @param value
* @return
* @throws Exception
* @author tanyaowu
*/
public static Object convert(Class> type, String value) throws Exception {
if (type == String.class) {
return value;
} else {
if (isBlank(value)) {
return null;
}
if (type == Byte.class || type == byte.class) {
return Byte.parseByte(value);
} else if (type == Short.class || type == short.class) {
return Short.parseShort(value);
} else if (type == Integer.class || type == int.class) {
return Integer.parseInt(value);
} else if (type == Long.class || type == long.class) {
return Long.parseLong(value);
} else if (type == Float.class || type == float.class) {
return Float.parseFloat(value);
} else if (type == Double.class || type == double.class) {
return Double.parseDouble(value);
} else if (type == Character.class || type == char.class) {
return Character.valueOf(value.charAt(0));
} else if (type == Boolean.class || type == boolean.class) {
return "1".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value);
} else if (type == BigDecimal.class) {
return new BigDecimal(value);
} else if (type == BigInteger.class) {
return new BigInteger(value);
} else if (type == Number.class) {
return NumberFormat.getInstance().parse(value);
} else if (type == Date.class) {
return DateUtil.parseToDate(value);
} else if (type == java.sql.Date.class) {
return DateUtil.parseToSqlDate(value);
} else if (type == java.sql.Timestamp.class) {
return DateUtil.parseToTimestamp(value);
} else if (type == java.sql.Time.class) {
return DateUtil.parseToTime(value);
}
}
throw new Exception("不知道要转换成啥" + type);
}
/**
*
* @param type
* @param values
* @return 返回的也是一个数组
* @throws Exception
* @author tanyaowu
*/
// @SuppressWarnings("unchecked")
public static Object convert(Class> type, String[] values) throws Exception {
if (values == null) {
return null;
}
Class> componentType = null;
if (type.isArray()) {
componentType = type.getComponentType();
} else {
componentType = type;
}
if (componentType.isPrimitive()) {
if (componentType == int.class) {
int[] ret = new int[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Integer.parseInt(values[i]);
}
return ret;
} else if (componentType == long.class) {
long[] ret = new long[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Long.parseLong(values[i]);
}
return ret;
} else if (componentType == short.class) {
short[] ret = new short[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Short.parseShort(values[i]);
}
return ret;
} else if (componentType == double.class) {
double[] ret = new double[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Double.parseDouble(values[i]);
}
return ret;
} else if (componentType == float.class) {
float[] ret = new float[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Float.parseFloat(values[i]);
}
return ret;
} else if (componentType == byte.class) {
byte[] ret = new byte[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Byte.parseByte(values[i]);
}
return ret;
} else if (componentType == boolean.class) {
boolean[] ret = new boolean[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = false;
continue;
}
ret[i] = "1".equalsIgnoreCase(values[i]) || "true".equalsIgnoreCase(values[i]) || "yes".equalsIgnoreCase(values[i]);
}
return ret;
} else if (componentType == char.class) {
char[] ret = new char[values.length];
for (int i = 0; i < ret.length; i++) {
if (isBlank(values[i])) {
ret[i] = 0;
continue;
}
ret[i] = Character.valueOf(values[i].charAt(0));
}
return ret;
}
return null;
} else {
Object[] ret = ArrayUtil.newArray(componentType, values.length);
for (int i = 0; i < ret.length; i++) {
ret[i] = convert(componentType, values[i]);
}
return ret;
}
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param testStrs 需要检查的字符串数组
* @return 是否包含任意一个字符串
* @since 3.2.0
*/
public static boolean containsAny(CharSequence str, CharSequence... testStrs) {
return null != getContainsStr(str, testStrs);
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串,如果包含返回找到的第一个字符串
*
* @param str 指定字符串
* @param testStrs 需要检查的字符串数组
* @return 被包含的第一个字符串
* @since 3.2.0
*/
public static String getContainsStr(CharSequence str, CharSequence... testStrs) {
if (isEmpty(str) || testStrs == null) {
return null;
}
for (CharSequence checkStr : testStrs) {
if (str.toString().contains(checkStr)) {
return checkStr.toString();
}
}
return null;
}
/**
* 大写首字母
* 例如:str = name, return Name
*
* @param str 字符串
* @return 字符串
*/
public static String upperFirst(CharSequence str) {
if (null == str) {
return null;
}
if (str.length() > 0) {
char firstChar = str.charAt(0);
if (Character.isLowerCase(firstChar)) {
return Character.toUpperCase(firstChar) + subSuf(str, 1);
}
}
return str.toString();
}
/**
* 小写首字母
* 例如:str = Name, return name
*
* @param str 字符串
* @return 字符串
*/
public static String lowerFirst(CharSequence str) {
if (null == str) {
return null;
}
if (str.length() > 0) {
char firstChar = str.charAt(0);
if (Character.isUpperCase(firstChar)) {
return Character.toLowerCase(firstChar) + subSuf(str, 1);
}
}
return str.toString();
}
/**
* 字符串转换成驼峰格式
*
*
* toLowerCaseAnyway 参数的作用如下:
*
* 1:当待转换字符串中包含下划线字符 '_' 时,无需关心 toLowerCaseAnyway 参数的值,转换结果始终一样
*
* 2:当待转换字符串中不包含下划线字符 '_' 时,toLowerCaseAnyway 参数规则如下:
* true 值: 将待转换字符串全部转换成小与字母,适用于 oralce 数据库字段转换的场景
* 因为 oracle 字段全是大写字母
*
* false 值: 则原样返回待转换字符串,适用于待转换字符串可能原本就是驼峰格式的场景
* 如果原本就是驼峰,全部转成小写字母显然不合理
*
*/
public static String toCamelCase(String str, boolean toLowerCaseAnyway) {
int len = str.length();
if (len <= 1) {
return str;
}
char ch;
int index = 0;
char[] buf = new char[len];
int i = 0;
for (; i < len; i++) {
ch = str.charAt(i);
if (ch == '_') {
// 当前字符为下划线时,将指针后移一位,将紧随下划线后面一个字符转成大写并存放
i++;
if (i < len) {
ch = str.charAt(i);
buf[index] = (index == 0 ? // 首字母无条件变小写
Character.toLowerCase(ch) : Character.toUpperCase(ch));
index++;
}
} else {
buf[index++] = Character.toLowerCase(ch);
}
}
if (toLowerCaseAnyway) {
return new String(buf, 0, index);
}
// i == index 时,表明字符串中不存在字符 '_'
// 无下划线的字符串原本可能就是驼峰形式,所以原样返回
return i == index ? str : new String(buf, 0, index);
}
/**
* 首字母变小写
*
* @param str
* @return
*/
public static String firstCharToLowerCase(String str) {
char firstChar = str.charAt(0);
if (firstChar >= 'A' && firstChar <= 'Z') {
char[] arr = str.toCharArray();
arr[0] += ('a' - 'A');
return new String(arr);
}
return str;
}
public static boolean isNotEmpty(String str) {
return str != null && !str.isEmpty();
}
public static boolean notEmpty(String str) {
return str != null && !str.isEmpty();
}
}