top.jfunc.common.utils.StrUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
common utils like IOUtil,StrUtil,HoldProcessor.etc.
package top.jfunc.common.utils;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* 字符串工具类
*
* @author xiaoleilu
*
*/
public class StrUtil {
private StrUtil(){}
public static final int INDEX_NOT_FOUND = -1;
public static final char C_SPACE = ' ';
public static final char C_TAB = ' ';
public static final char C_DOT = '.';
public static final char C_SLASH = '/';
public static final char C_BACKSLASH = '\\';
public static final char C_CR = '\r';
public static final char C_LF = '\n';
public static final char C_UNDERLINE = '_';
public static final char C_COMMA = ',';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
public static final char C_BRACKET_START = '[';
public static final char C_BRACKET_END = ']';
public static final char C_COLON = ':';
public static final String SPACE = " ";
public static final String TAB = " ";
public static final String DOT = ".";
public static final String DOUBLE_DOT = "..";
public static final String SLASH = "/";
public static final String BACKSLASH = "\\";
public static final String EMPTY = "";
public static final String CR = "\r";
public static final String LF = "\n";
public static final String CRLF = "\r\n";
public static final String UNDERLINE = "_";
public static final String COMMA = ",";
public static final String DELIM_START = "{";
public static final String DELIM_END = "}";
public static final String BRACKET_START = "[";
public static final String BRACKET_END = "]";
public static final String COLON = ":";
public static final String HTML_NBSP = " ";
public static final String HTML_AMP = "&";
public static final String HTML_QUOTE = """;
public static final String HTML_LT = "<";
public static final String HTML_GT = ">";
public static final String EMPTY_JSON = "{}";
// ------------------------------------------------------------------------ Blank
/**
* 字符串是否为空白 空白的定义如下:
* 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 == NumberUtil.isBlankChar(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* 字符串是否为非空白 空白的定义如下:
* 1、不为null
* 2、不为不可见字符(如空格)
* 3、不为""
*
* @param str 被检测的字符串
* @return 是否为非空
*/
public static boolean isNotBlank(CharSequence str) {
return !isBlank(str);
}
/**
* 是否包含空字符串
*
* @param strs 字符串列表
* @return 是否包含空字符串
*/
public static boolean hasBlank(CharSequence... strs) {
if (ArrayUtil.isEmpty(strs)) {
return true;
}
for (CharSequence str : strs) {
if (isBlank(str)) {
return true;
}
}
return false;
}
/**
* 给定所有字符串是否为空白
*
* @param strs 字符串
* @return 所有字符串是否为空白
*/
public static boolean isAllBlank(CharSequence... strs) {
if (ArrayUtil.isEmpty(strs)) {
return true;
}
for (CharSequence str : strs) {
if (isNotBlank(str)) {
return false;
}
}
return true;
}
// ------------------------------------------------------------------------ Empty
/**
* 字符串是否为空,空的定义如下 1、为null
* 2、为""
*
* @param str 被检测的字符串
* @return 是否为空
*/
public static boolean isEmpty(CharSequence str) {
return str == null || str.length() == 0;
}
/**
* 字符串是否为非空白 空白的定义如下:
* 1、不为null
* 2、不为""
*
* @param str 被检测的字符串
* @return 是否为非空
*/
public static boolean isNotEmpty(CharSequence str) {
return false == isEmpty(str);
}
/**
* 当给定字符串为null时,转换为Empty
*
* @param str 被转换的字符串
* @return 转换后的字符串
*/
public static String nullToEmpty(CharSequence str) {
return nullToDefault(str, EMPTY);
}
/**
* 如果字符串是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();
}
/**
* 当给定字符串为空字符串时,转换为null
*
* @param str 被转换的字符串
* @return 转换后的字符串
*/
public static String emptyToNull(CharSequence str) {
return isEmpty(str) ? null : str.toString();
}
/**
* 是否包含空字符串
*
* @param strs 字符串列表
* @return 是否包含空字符串
*/
public static boolean hasEmpty(CharSequence... strs) {
if (ArrayUtil.isEmpty(strs)) {
return true;
}
for (CharSequence str : strs) {
if (isEmpty(str)) {
return true;
}
}
return false;
}
/**
* 是否全部为空字符串
*
* @param strs 字符串列表
* @return 是否全部为空字符串
*/
public static boolean isAllEmpty(CharSequence... strs) {
if (ArrayUtil.isEmpty(strs)) {
return true;
}
for (CharSequence str : strs) {
if (isNotEmpty(str)) {
return false;
}
}
return true;
}
// ------------------------------------------------------------------------ Trim
/**
* 除去字符串头尾部的空白,如果字符串是null
,依然返回null
。
*
*
* 注意,和String.trim
不同,此方法使用NumberUtil.isBlankChar
来判定空白, 因而可以除去英文字符集之外的其它空白,如中文空格。
*
*
* trim(null) = null
* trim("") = ""
* trim(" ") = ""
* trim("abc") = "abc"
* trim(" abc ") = "abc"
*
*
* @param str 要处理的字符串
*
* @return 除去头尾空白的字符串,如果原字串为null
,则返回null
*/
public static String trim(CharSequence str) {
return (null == str) ? null : trim(str, 0);
}
/**
* 给定字符串数组全部做去首尾空格
*
* @param strs 字符串数组
*/
public static void trim(String[] strs) {
if (null == strs) {
return;
}
String str;
for (int i = 0; i < strs.length; i++) {
str = strs[i];
if (null != str) {
strs[i] = str.trim();
}
}
}
/**
* 除去字符串头尾部的空白,如果字符串是{@code null},返回""
。
*
*
* 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, 0);
}
/**
* 除去字符串头部的空白,如果字符串是null
,则返回null
。
*
*
* 注意,和String.trim
不同,此方法使用NumberUtil.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
不同,此方法使用NumberUtil.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
*/
public 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) && (NumberUtil.isBlankChar(str.charAt(start)))) {
start++;
}
}
// 扫描字符串尾部
if (mode >= 0) {
while ((start < end) && (NumberUtil.isBlankChar(str.charAt(end - 1)))) {
end--;
}
}
if ((start > 0) || (end < length)) {
return str.toString().substring(start, end);
}
return str.toString();
}
/**
* 字符串是否以给定字符开始
*
* @param str 字符串
* @param c 字符
* @return 是否开始
*/
public static boolean startWith(CharSequence str, char c) {
return c == str.charAt(0);
}
/**
* 是否以指定字符串开头
* 如果给定的字符串和开头字符串都为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());
}
}
/**
* 是否以指定字符串开头
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @return 是否以指定字符串开头
*/
public static boolean startWith(CharSequence str, CharSequence prefix) {
return startWith(str, prefix, false);
}
/**
* 是否以指定字符串开头,忽略大小写
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @return 是否以指定字符串开头
*/
public static boolean startWithIgnoreCase(CharSequence str, CharSequence prefix) {
return startWith(str, prefix, true);
}
/**
* 给定字符串是否以任何一个字符串开始
* 给定字符串和数组为空都返回false
*
* @param str 给定字符串
* @param prefixes 需要检测的开始字符串
* @return 给定字符串是否以任何一个字符串开始
* @since 3.0.6
*/
public static boolean startWithAny(CharSequence str, CharSequence... prefixes) {
if (isEmpty(str) || ArrayUtil.isEmpty(prefixes)) {
return false;
}
for (CharSequence suffix : prefixes) {
if (startWith(str, suffix, false)) {
return true;
}
}
return 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);
}
/**
* 给定字符串是否以任何一个字符串结尾
* 给定字符串和数组为空都返回false
*
* @param str 给定字符串
* @param suffixes 需要检测的结尾字符串
* @return 给定字符串是否以任何一个字符串结尾
* @since 3.0.6
*/
public static boolean endWithAny(CharSequence str, CharSequence... suffixes) {
if (isEmpty(str) || ArrayUtil.isEmpty(suffixes)) {
return false;
}
for (CharSequence suffix : suffixes) {
if (endWith(str, suffix, false)) {
return true;
}
}
return false;
}
/**
* 指定字符是否在字符串中出现过
* @param str 字符串
* @param searchChar 被查找的字符
* @return 是否包含
* @since 3.1.2
*/
public static boolean contains(CharSequence str, char searchChar) {
return indexOf(str, searchChar) > -1;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串
*
* @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) || ArrayUtil.isEmpty(testStrs)) {
return null;
}
for (CharSequence checkStr : testStrs) {
if(str.toString().contains(checkStr)) {
return checkStr.toString();
}
}
return null;
}
/**
* 是否包含特定字符,忽略大小写,如果给定两个参数都为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 testStrs 需要检查的字符串数组
* @return 是否包含任意一个字符串
* @since 3.2.0
*/
public static boolean containsAnyIgnoreCase(CharSequence str, CharSequence... testStrs) {
return null != getContainsStrIgnoreCase(str, testStrs);
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串,如果包含返回找到的第一个字符串
* 忽略大小写
*
* @param str 指定字符串
* @param testStrs 需要检查的字符串数组
* @return 被包含的第一个字符串
* @since 3.2.0
*/
public static String getContainsStrIgnoreCase(CharSequence str, CharSequence... testStrs) {
if(isEmpty(str) || ArrayUtil.isEmpty(testStrs)) {
return null;
}
for (CharSequence testStr : testStrs) {
if(containsIgnoreCase(str, testStr)) {
return testStr.toString();
}
}
return null;
}
/**
* 获得set或get方法对应的标准属性名
* 例如:setName 返回 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);
}
return null;
}
/**
* 生成set方法名
* 例如:name 返回 setName
*
* @param fieldName 属性名
* @return setXxx
*/
public static String genSetter(CharSequence fieldName) {
return upperFirstAndAddPre(fieldName, "set");
}
/**
* 生成get方法名
*
* @param fieldName 属性名
* @return getXxx
*/
public static String genGetter(String fieldName) {
return upperFirstAndAddPre(fieldName, "get");
}
/**
* 移除字符串中所有给定字符串
* 例:removeAll("aa-bb-cc-dd", "-") =》 aabbccdd
*
* @param str 字符串
* @param strToRemove 被移除的字符串
* @return 移除后的字符串
*/
public static String removeAll(String str, CharSequence strToRemove) {
return str.replace(strToRemove, EMPTY);
}
/**
* 去掉首部指定长度的字符串并将剩余字符串首字母小写
* 例如:str=setName, preLength=3 =》 return name
*
* @param str 被处理的字符串
* @param preLength 去掉的长度
* @return 处理后的字符串,不符合规范返回null
*/
public static String removePreAndLowerFirst(CharSequence str, int preLength) {
if (str == null) {
return null;
}
if (str.length() > preLength) {
char first = Character.toLowerCase(str.charAt(preLength));
if (str.length() > preLength + 1) {
return first + str.toString().substring(preLength + 1);
}
return String.valueOf(first);
} else {
return str.toString();
}
}
/**
* 去掉首部指定长度的字符串并将剩余字符串首字母小写
* 例如:str=setName, prefix=set =》 return name
*
* @param str 被处理的字符串
* @param prefix 前缀
* @return 处理后的字符串,不符合规范返回null
*/
public static String removePreAndLowerFirst(CharSequence str, CharSequence prefix) {
return lowerFirst(removePrefix(str, prefix));
}
/**
* 原字符串首字母大写并在其首部添加指定字符串 例如:str=name, preString=get =》 return getName
*
* @param str 被处理的字符串
* @param preString 添加的首部
* @return 处理后的字符串
*/
public static String upperFirstAndAddPre(CharSequence str, String preString) {
if (str == null || preString == null) {
return null;
}
return preString + upperFirst(str);
}
/**
* 大写首字母
* 例如: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();
}
/**
* 去掉指定前缀
*
* @param str 字符串
* @param prefix 前缀
* @return 切掉后的字符串,若前缀不是 preffix, 返回原字符串
*/
public static String removePrefix(CharSequence str, CharSequence prefix) {
if (isEmpty(str) || isEmpty(prefix)) {
return str(str);
}
final String str2 = str.toString();
if (str2.startsWith(prefix.toString())) {
return subSuf(str2, prefix.length());// 截取后半段
}
return str2;
}
/**
* 忽略大小写去掉指定前缀
*
* @param str 字符串
* @param prefix 前缀
* @return 切掉后的字符串,若前缀不是 prefix, 返回原字符串
*/
public static String removePrefixIgnoreCase(CharSequence str, CharSequence prefix) {
if (isEmpty(str) || isEmpty(prefix)) {
return str(str);
}
final String str2 = str.toString();
if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) {
return subSuf(str2, prefix.length());// 截取后半段
}
return str2;
}
/**
* 去掉指定后缀
*
* @param str 字符串
* @param suffix 后缀
* @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
*/
public static String removeSuffix(CharSequence str, CharSequence suffix) {
if (isEmpty(str) || isEmpty(suffix)) {
return str(str);
}
final String str2 = str.toString();
if (str2.endsWith(suffix.toString())) {
return subPre(str2, str2.length() - suffix.length());// 截取前半段
}
return str2;
}
/**
* 去掉指定后缀,并小写首字母
*
* @param str 字符串
* @param suffix 后缀
* @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
*/
public static String removeSufAndLowerFirst(CharSequence str, CharSequence suffix) {
return lowerFirst(removeSuffix(str, suffix));
}
/**
* 忽略大小写去掉指定后缀
*
* @param str 字符串
* @param suffix 后缀
* @return 切掉后的字符串,若后缀不是 suffix, 返回原字符串
*/
public static String removeSuffixIgnoreCase(CharSequence str, CharSequence suffix) {
if (isEmpty(str) || isEmpty(suffix)) {
return str(str);
}
final String str2 = str.toString();
if (str2.toLowerCase().endsWith(suffix.toString().toLowerCase())) {
return subPre(str2, str2.length() - suffix.length());
}
return str2;
}
/**
* 去除两边的指定字符串
*
* @param str 被处理的字符串
* @param prefixOrSuffix 前缀或后缀
* @return 处理后的字符串
* @since 3.1.2
*/
public static String strip(CharSequence str, CharSequence prefixOrSuffix) {
return strip(str, prefixOrSuffix, prefixOrSuffix);
}
/**
* 去除两边的指定字符串
*
* @param str 被处理的字符串
* @param prefix 前缀
* @param suffix 后缀
* @return 处理后的字符串
* @since 3.1.2
*/
public static String strip(CharSequence str, CharSequence prefix, CharSequence suffix) {
if(isEmpty(str)) {
return str(str);
}
int from = 0;
int to = str.length();
String str2 = str.toString();
if(startWith(str2, prefix)) {
from = prefix.length();
}
if(endWith(str2, suffix)) {
to -= suffix.length();
}
return str2.substring(from, to);
}
/**
* 去除两边的指定字符串,忽略大小写
*
* @param str 被处理的字符串
* @param prefixOrSuffix 前缀或后缀
* @return 处理后的字符串
* @since 3.1.2
*/
public static String stripIgnoreCase(CharSequence str, CharSequence prefixOrSuffix) {
return stripIgnoreCase(str, prefixOrSuffix, prefixOrSuffix);
}
/**
* 去除两边的指定字符串,忽略大小写
*
* @param str 被处理的字符串
* @param prefix 前缀
* @param suffix 后缀
* @return 处理后的字符串
* @since 3.1.2
*/
public static String stripIgnoreCase(CharSequence str, CharSequence prefix, CharSequence suffix) {
if(isEmpty(str)) {
return str(str);
}
int from = 0;
int to = str.length();
String str2 = str.toString();
if(startWithIgnoreCase(str2, prefix)) {
from = prefix.length();
}
if(endWithIgnoreCase(str2, suffix)) {
to -= suffix.length();
}
return str2.substring(from, to);
}
/**
* 如果给定字符串不是以prefix开头的,在开头补充 prefix
*
* @param str 字符串
* @param prefix 前缀
* @return 补充后的字符串
*/
public static String addPrefixIfNot(CharSequence str, CharSequence prefix) {
if (isEmpty(str) || isEmpty(prefix)) {
return str(str);
}
final String str2 = str.toString();
final String prefix2 = prefix.toString();
if (false == str2.startsWith(prefix2)) {
return prefix2.concat(str2);
}
return str2;
}
/**
* 如果给定字符串不是以suffix结尾的,在尾部补充 suffix
*
* @param str 字符串
* @param suffix 后缀
* @return 补充后的字符串
*/
public static String addSuffixIfNot(CharSequence str, CharSequence suffix) {
if (isEmpty(str) || isEmpty(suffix)) {
return str(str);
}
final String str2 = str.toString();
final String suffix2 = suffix.toString();
if (false == str2.endsWith(suffix2)) {
return str2.concat(suffix2);
}
return str2;
}
/**
* 清理空白字符
*
* @param str 被清理的字符串
* @return 清理后的字符串
*/
public static String cleanBlank(CharSequence str) {
if (str == null) {
return null;
}
int len = str.length();
final StringBuilder sb = new StringBuilder(len);
char c;
for (int i = 0; i < len; i++) {
c = str.charAt(i);
if (false == NumberUtil.isBlankChar(c)) {
sb.append(c);
}
}
return sb.toString();
}
//------------------------------------------------------------------------------ Split
/**
* 切分字符串
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @return 切分后的集合
*/
public static String[] splitToArray(CharSequence str, char separator) {
return splitToArray(str, separator, 0);
}
/**
* 切分字符串
* a#b#c =》 [a,b,c]
* a##b#c =》 [a,"",b,c]
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @return 切分后的集合
*/
public static List split(CharSequence str, char separator) {
return split(str, separator, 0);
}
/**
* 切分字符串
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数
* @return 切分后的集合
*/
public static String[] splitToArray(CharSequence str, char separator, int limit) {
if (null == str) {
return new String[] {};
}
return StrSpliter.splitToArray(str.toString(), separator, limit, false, false);
}
/**
* 切分字符串,不去除切分后每个元素两边的空白符,不去除空白项
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数,-1不限制
* @return 切分后的集合
*/
public static List split(CharSequence str, char separator, int limit) {
return split(str, separator, limit, false, false);
}
/**
* 切分字符串,去除切分后每个元素两边的空白符,去除空白项
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @return 切分后的集合
* @since 3.1.2
*/
public static List splitTrim(CharSequence str, char separator) {
return splitTrim(str, separator, -1);
}
/**
* 切分字符串,去除切分后每个元素两边的空白符,去除空白项
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @return 切分后的集合
* @since 3.2.0
*/
public static List splitTrim(CharSequence str, CharSequence separator) {
return splitTrim(str, separator, -1);
}
/**
* 切分字符串,去除切分后每个元素两边的空白符,去除空白项
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数,-1不限制
* @return 切分后的集合
* @since 3.1.0
*/
public static List splitTrim(CharSequence str, char separator, int limit) {
return split(str, separator, limit, true, true);
}
/**
* 切分字符串,去除切分后每个元素两边的空白符,去除空白项
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数,-1不限制
* @return 切分后的集合
* @since 3.2.0
*/
public static List splitTrim(CharSequence str, CharSequence separator, int limit) {
return split(str, separator, limit, true, true);
}
/**
* 切分字符串,不限制分片数量
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param isTrim 是否去除切分字符串后每个元素两边的空格
* @param ignoreEmpty 是否忽略空串
* @return 切分后的集合
* @since 3.0.8
*/
public static List split(CharSequence str, char separator, boolean isTrim, boolean ignoreEmpty) {
return split(str, separator, 0, isTrim, ignoreEmpty);
}
/**
* 切分字符串
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数,-1不限制
* @param isTrim 是否去除切分字符串后每个元素两边的空格
* @param ignoreEmpty 是否忽略空串
* @return 切分后的集合
* @since 3.0.8
*/
public static List split(CharSequence str, char separator, int limit, boolean isTrim, boolean ignoreEmpty) {
if (null == str) {
return new ArrayList<>(0);
}
return StrSpliter.split(str.toString(), separator, limit, isTrim, ignoreEmpty);
}
/**
* 切分字符串
*
* @param str 被切分的字符串
* @param separator 分隔符字符
* @param limit 限制分片数,-1不限制
* @param isTrim 是否去除切分字符串后每个元素两边的空格
* @param ignoreEmpty 是否忽略空串
* @return 切分后的集合
* @since 3.2.0
*/
public static List split(CharSequence str, CharSequence separator, int limit, boolean isTrim, boolean ignoreEmpty) {
if (null == str) {
return new ArrayList<>(0);
}
final String separatorStr = (null == separator) ? null : separator.toString();
return StrSpliter.split(str.toString(), separatorStr, limit, isTrim, ignoreEmpty);
}
/**
* 切分字符串
*
* @param str 被切分的字符串
* @param separator 分隔符
* @return 字符串
*/
public static String[] split(CharSequence str, CharSequence separator) {
if (str == null) {
return new String[] {};
}
final String separatorStr = (null == separator) ? null : separator.toString();
return StrSpliter.splitToArray(str.toString(), separatorStr, 0, false, false);
}
/**
* 根据给定长度,将给定字符串截取为多个部分
*
* @param str 字符串
* @param len 每一个小节的长度
* @return 截取后的字符串数组
* @see StrSpliter#splitByLength(String, int)
*/
public static String[] split(CharSequence str, int len) {
if (null == str) {
return new String[] {};
}
return StrSpliter.splitByLength(str.toString(), len);
}
/**
* 改进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 string String
* @param fromIndex 开始的index(包括)
* @param toIndex 结束的index(不包括)
* @return 字串
*/
public static String sub(CharSequence string, int fromIndex, int toIndex) {
int len = string.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 string.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(CharsetUtil.CHARSET_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, CharsetUtil.CHARSET_GBK) + suffix;
}
/**
* 切割前部分
*
* @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());
}
/**
* 截取分隔字符串之前的字符串,不包括分隔字符串
* 如果给定的字符串为空串(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 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) {
return EMPTY;
}
if (count == 1 || str.length() == 0) {
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);
}
/**
* 比较两个字符串(大小写敏感)。
*
*
* 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 (str1 == null) {
return str2 == null;
}
if(ignoreCase) {
return str1.toString().equalsIgnoreCase(str2.toString());
}else {
return str1.equals(str2);
}
}
/**
* 格式化文本, {} 表示占位符
* 此方法只是简单将占位符 {} 按照顺序替换为参数
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
* 例:
* 通常使用:format("this is {} for {}", "a", "b") =》 this is a for b
* 转义{}: format("this is \\{} for {}", "a", "b") =》 this is \{} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") =》 this is \a for b
*
* @param template 文本模板,被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(CharSequence template, Object... params) {
if (null == template) {
return null;
}
if (ArrayUtil.isEmpty(params) || isBlank(template)) {
return template.toString();
}
return StrFormatter.format(template.toString(), params);
}
/**
* 有序的格式化文本,使用{number}做为占位符
* 例:
* 通常使用:format("this is {0} for {1}", "a", "b") =》 this is a for b
*
* @param pattern 文本格式
* @param arguments 参数
* @return 格式化后的文本
*/
public static String indexedFormat(CharSequence pattern, Object... arguments) {
return MessageFormat.format(pattern.toString(), arguments);
}
/**
* 格式化文本,使用 {varName} 占位
* map = {a: "aValue", b: "bValue"} format("{a} and {b}", map) ---=》 aValue and bValue
*
* @param template 文本模板,被替换的部分用 {key} 表示
* @param map 参数值对
* @return 格式化后的文本
*/
public static String format(CharSequence template, Map, ?> map) {
if (null == template) {
return null;
}
if (null == map || map.isEmpty()) {
return template.toString();
}
String template2 = template.toString();
for (Entry, ?> entry : map.entrySet()) {
template2 = template2.replace("{" + entry.getKey() + "}", utf8Str(entry.getValue()));
}
return template2;
}
/**
* 编码字符串,编码为UTF-8
*
* @param str 字符串
* @return 编码后的字节码
*/
public static byte[] utf8Bytes(CharSequence str) {
return bytes(str, CharsetUtil.CHARSET_UTF_8);
}
/**
* 编码字符串
* 使用系统默认编码
*
* @param str 字符串
* @return 编码后的字节码
*/
public static byte[] bytes(CharSequence str) {
return bytes(str, Charset.defaultCharset());
}
/**
* 编码字符串
*
* @param str 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 编码后的字节码
*/
public static byte[] bytes(CharSequence str, String charset) {
return bytes(str, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
}
/**
* 编码字符串
*
* @param str 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 编码后的字节码
*/
public static byte[] bytes(CharSequence str, Charset charset) {
if (str == null) {
return null;
}
if (null == charset) {
return str.toString().getBytes();
}
return str.toString().getBytes(charset);
}
/**
* 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法
*
* @param obj 对象
* @return 字符串
*/
public static String utf8Str(Object obj) {
return str(obj, CharsetUtil.CHARSET_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();
}
/**
* 将byte数组转为字符串
*
* @param bytes byte数组
* @param charset 字符集
* @return 字符串
*/
public static String str(byte[] bytes, String charset) {
return str(bytes, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
}
/**
* 解码字节码
*
* @param data 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 解码后的字符串
*/
public static String str(byte[] data, Charset charset) {
if (data == null) {
return null;
}
if (null == charset) {
return new String(data);
}
return new String(data, charset);
}
/**
* 将Byte数组转为字符串
*
* @param bytes byte数组
* @param charset 字符集
* @return 字符串
*/
public static String str(Byte[] bytes, String charset) {
return str(bytes, isBlank(charset) ? Charset.defaultCharset() : Charset.forName(charset));
}
/**
* 解码字节码
*
* @param data 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 解码后的字符串
*/
public static String str(Byte[] data, Charset charset) {
if (data == null) {
return null;
}
byte[] bytes = new byte[data.length];
Byte dataByte;
for (int i = 0; i < data.length; i++) {
dataByte = data[i];
bytes[i] = (null == dataByte) ? -1 : dataByte.byteValue();
}
return str(bytes, charset);
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, String charset) {
if (data == null) {
return null;
}
return str(data, Charset.forName(charset));
}
/**
* 将编码的byteBuffer数据转换为字符串
*
* @param data 数据
* @param charset 字符集,如果为空使用当前系统字符集
* @return 字符串
*/
public static String str(ByteBuffer data, Charset charset) {
if (null == charset) {
charset = Charset.defaultCharset();
}
return charset.decode(data).toString();
}
/**
* {@link CharSequence} 转为字符串,null安全
* @param cs {@link CharSequence}
* @return 字符串
*/
public static String str(CharSequence cs) {
return null == cs ? null : cs.toString();
}
/**
* 字符串转换为byteBuffer
*
* @param str 字符串
* @param charset 编码
* @return byteBuffer
*/
public static ByteBuffer byteBuffer(CharSequence str, String charset) {
return ByteBuffer.wrap(bytes(str, charset));
}
/**
* 以 conjunction 为分隔符将多个对象转换为字符串
*
* @see ArrayUtil#join(Object, CharSequence)
*
* @param conjunction 分隔符
* @param objs 数组
* @return 连接后的字符串
*/
public static String join(CharSequence conjunction, Object... objs) {
return ArrayUtil.join(objs, conjunction);
}
/**
* 将驼峰式命名的字符串转换为下划线方式。如果转换前的驼峰式命名的字符串为空,则返回空字符串。
* 例如:HelloWorld=》hello_world
*
* @param camelCaseStr 转换前的驼峰式命名的字符串
* @return 转换后下划线大写方式命名的字符串
*/
public static String toUnderlineCase(CharSequence camelCaseStr) {
if (camelCaseStr == null) {
return null;
}
final int length = camelCaseStr.length();
StringBuilder sb = new StringBuilder();
char c;
boolean isPreUpperCase = false;
for (int i = 0; i < length; i++) {
c = camelCaseStr.charAt(i);
boolean isNextUpperCase = true;
if (i < (length - 1)) {
isNextUpperCase = Character.isUpperCase(camelCaseStr.charAt(i + 1));
}
if (Character.isUpperCase(c)) {
if (!isPreUpperCase || !isNextUpperCase) {
if (i > 0) {
sb.append(UNDERLINE);
}
}
isPreUpperCase = true;
} else {
isPreUpperCase = false;
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 将下划线方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。
* 例如:hello_world=》HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String toCamelCase(CharSequence name) {
if (null == name) {
return null;
}
String name2 = name.toString();
if (name2.contains(UNDERLINE)) {
name2 = name2.toLowerCase();
StringBuilder sb = new StringBuilder(name2.length());
boolean upperCase = false;
for (int i = 0; i < name2.length(); i++) {
char c = name2.charAt(i);
if (c == '_') {
upperCase = true;
} else if (upperCase) {
sb.append(Character.toUpperCase(c));
upperCase = false;
} else {
sb.append(c);
}
}
return sb.toString();
} else {
return name2;
}
}
/**
* 包装指定字符串
* 当前缀和后缀一致时使用此方法
*
* @param str 被包装的字符串
* @param prefixAndSuffix 前缀和后缀
* @return 包装后的字符串
* @since 3.1.0
*/
public static String wrap(CharSequence str, CharSequence prefixAndSuffix) {
return wrap(str, prefixAndSuffix, prefixAndSuffix);
}
/**
* 包装指定字符串
*
* @param str 被包装的字符串
* @param prefix 前缀
* @param suffix 后缀
* @return 包装后的字符串
*/
public static String wrap(CharSequence str, CharSequence prefix, CharSequence suffix) {
return nullToEmpty(prefix).concat(nullToEmpty(str)).concat(nullToEmpty(suffix));
}
/**
* 包装指定字符串,如果前缀或后缀已经包含对应的字符串,则不再
*
* @param str 被包装的字符串
* @param prefix 前缀
* @param suffix 后缀
* @return 包装后的字符串
*/
public static String wrapIfMissing(CharSequence str, CharSequence prefix, CharSequence suffix) {
int len = 0;
if (isNotEmpty(str)) {
len += str.length();
}
if (isNotEmpty(prefix)) {
len += str.length();
}
if (isNotEmpty(suffix)) {
len += str.length();
}
StringBuilder sb = new StringBuilder(len);
if (isNotEmpty(prefix) && false == startWith(str, prefix)) {
sb.append(prefix);
}
if (isNotEmpty(str)) {
sb.append(str);
}
if (isNotEmpty(suffix) && false == endWith(str, suffix)) {
sb.append(suffix);
}
return sb.toString();
}
/**
* 指定字符串是否被包装
*
* @param str 字符串
* @param prefix 前缀
* @param suffix 后缀
* @return 是否被包装
*/
public static boolean isWrap(CharSequence str, String prefix, String suffix) {
if (ArrayUtil.hasNull(str, prefix, suffix)) {
return false;
}
final String str2 = str.toString();
return str2.startsWith(prefix) && str2.endsWith(suffix);
}
/**
* 指定字符串是否被同一字符包装(前后都有这些字符串)
*
* @param str 字符串
* @param wrapper 包装字符串
* @return 是否被包装
*/
public static boolean isWrap(CharSequence str, String wrapper) {
return isWrap(str, wrapper, wrapper);
}
/**
* 指定字符串是否被同一字符包装(前后都有这些字符串)
*
* @param str 字符串
* @param wrapper 包装字符
* @return 是否被包装
*/
public static boolean isWrap(CharSequence str, char wrapper) {
return isWrap(str, wrapper, wrapper);
}
/**
* 指定字符串是否被包装
*
* @param str 字符串
* @param prefixChar 前缀
* @param suffixChar 后缀
* @return 是否被包装
*/
public static boolean isWrap(CharSequence str, char prefixChar, char suffixChar) {
if (null == str) {
return false;
}
return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar;
}
/**
* 补充字符串以满足最小长度 StrUtil.padPre("1", 3, '0');//"001"
*
* @param str 字符串
* @param minLength 最小长度
* @param padChar 补充的字符
* @return 补充后的字符串
*/
public static String padPre(CharSequence str, int minLength, char padChar) {
if (null == str) {
str = EMPTY;
} else if (str.length() >= minLength) {
return str.toString();
}
return repeat(padChar, minLength - str.length()).concat(str.toString());
}
/**
* 补充字符串以满足最小长度 StrUtil.padEnd("1", 3, '0');//"100"
*
* @param str 字符串,如果为null
,按照空串处理
* @param minLength 最小长度
* @param padChar 补充的字符
* @return 补充后的字符串
*/
public static String padEnd(CharSequence str, int minLength, char padChar) {
if (null == str) {
str = EMPTY;
} else if (str.length() >= minLength) {
return str.toString();
}
return str.toString().concat(repeat(padChar, minLength - str.length()));
}
/**
* 创建StringBuilder对象
*
* @return StringBuilder对象
*/
public static StringBuilder builder() {
return new StringBuilder();
}
/**
* 创建StringBuilder对象
*
* @param capacity 初始大小
* @return StringBuilder对象
*/
public static StringBuilder builder(int capacity) {
return new StringBuilder(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;
}
/**
* 获得StringReader
*
* @param str 字符串
* @return StringReader
*/
public static StringReader getReader(CharSequence str) {
if (null == str) {
return null;
}
return new StringReader(str.toString());
}
/**
* 获得StringWriter
*
* @return StringWriter
*/
public static StringWriter getWriter() {
return new StringWriter();
}
/**
* 统计指定内容中包含指定字符串的数量
* 参数为 {@code null} 或者 "" 返回 {@code 0}.
*
*
* 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() + 3) <= maxLength) {
return str.toString();
}
int w = maxLength / 2;
int l = str.length();
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(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().compareToIgnoreCase(str2.toString());
}
/**
* 指定范围内查找指定字符
*
* @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;
}
// ------------------------------------------------------------------------------------------------------------------ Append and prepend
/**
* 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串
* 不忽略大小写
*
* @param str 被检查的字符串
* @param suffix 需要添加到结尾的字符串
* @param suffixes 需要额外检查的结尾字符串,如果以这些中的一个为结尾,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String appendIfMissing(final CharSequence str, final CharSequence suffix, final CharSequence... suffixes) {
return appendIfMissing(str, suffix, false, suffixes);
}
/**
* 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串
* 忽略大小写
*
* @param str 被检查的字符串
* @param suffix 需要添加到结尾的字符串
* @param suffixes 需要额外检查的结尾字符串,如果以这些中的一个为结尾,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String appendIfMissingIgnoreCase(final CharSequence str, final CharSequence suffix, final CharSequence... suffixes) {
return appendIfMissing(str, suffix, true, suffixes);
}
/**
* 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串
*
* @param str 被检查的字符串
* @param suffix 需要添加到结尾的字符串
* @param ignoreCase 检查结尾时是否忽略大小写
* @param suffixes 需要额外检查的结尾字符串,如果以这些中的一个为结尾,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String appendIfMissing(final CharSequence str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
if (str == null || isEmpty(suffix) || endWith(str, suffix, ignoreCase)) {
return str(str);
}
if (suffixes != null && suffixes.length > 0) {
for (final CharSequence s : suffixes) {
if (endWith(str, s, ignoreCase)) {
return str.toString();
}
}
}
return str.toString().concat(suffix.toString());
}
/**
* 如果给定字符串不是以给定的一个或多个字符串为开头,则在首部添加起始字符串
* 不忽略大小写
*
* @param str 被检查的字符串
* @param prefix 需要添加到首部的字符串
* @param prefixes 需要额外检查的首部字符串,如果以这些中的一个为起始,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String prependIfMissing(final CharSequence str, final CharSequence prefix, final CharSequence... prefixes) {
return prependIfMissing(str, prefix, false, prefixes);
}
/**
* 如果给定字符串不是以给定的一个或多个字符串为开头,则在首部添加起始字符串
* 忽略大小写
*
* @param str 被检查的字符串
* @param prefix 需要添加到首部的字符串
* @param prefixes 需要额外检查的首部字符串,如果以这些中的一个为起始,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String prependIfMissingIgnoreCase(final CharSequence str, final CharSequence prefix, final CharSequence... prefixes) {
return prependIfMissing(str, prefix, true, prefixes);
}
/**
* 如果给定字符串不是以给定的一个或多个字符串为开头,则在首部添加起始字符串
*
* @param str 被检查的字符串
* @param prefix 需要添加到首部的字符串
* @param ignoreCase 检查结尾时是否忽略大小写
* @param prefixes 需要额外检查的首部字符串,如果以这些中的一个为起始,则不再添加
*
* @return 如果已经结尾,返回原字符串,否则返回添加结尾的字符串
* @since 3.0.7
*/
public static String prependIfMissing(final CharSequence str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
if (str == null || isEmpty(prefix) || startWith(str, prefix, ignoreCase)) {
return str(str);
}
if (prefixes != null && prefixes.length > 0) {
for (final CharSequence s : prefixes) {
if (startWith(str, s, ignoreCase)) {
return str.toString();
}
}
}
return prefix.toString().concat(str.toString());
}
/**
* 反转字符串
* 例如:abcd =》dcba
*
* @param str 被反转的字符串
* @return 反转后的字符串
* @since 3.0.9
*/
public static String reverse(String str) {
return new String(ArrayUtil.reverse(str.toCharArray()));
}
/**
* 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串
* 字符填充于字符串前
*
* @param str 被填充的字符串
* @param filledChar 填充的字符
* @param len 填充长度
* @return 填充后的字符串
* @since 3.1.2
*/
public static String fillBefore(String str, char filledChar, int len) {
return fill(str, filledChar, len, true);
}
/**
* 将已有字符串填充为规定长度,如果已有字符串超过这个长度则返回这个字符串
* 字符填充于字符串后
*
* @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 = StrUtil.repeat(filledChar, len - strLen);
return isPre ? filledStr.concat(str) : str.concat(filledStr);
}
}