This commit is contained in:
Looly
2023-03-25 11:36:23 +08:00
parent af1ac9c121
commit bece00d176
6 changed files with 156 additions and 81 deletions

View File

@@ -45,6 +45,16 @@ public class CharSequenceUtil extends StrChecker {
*/ */
public static final String SPACE = " "; public static final String SPACE = " ";
/**
* {@link CharSequence} 转为字符串null安全
*
* @param cs {@link CharSequence}
* @return 字符串
*/
public static String str(final CharSequence cs) {
return null == cs ? null : cs.toString();
}
/** /**
* 当给定字符串为null时转换为Empty * 当给定字符串为null时转换为Empty
* *
@@ -144,7 +154,7 @@ public class CharSequenceUtil extends StrChecker {
return handler.apply(str); return handler.apply(str);
} }
// ------------------------------------------------------------------------ Trim // region ----- trim
/** /**
* 除去字符串头尾部的空白,如果字符串是{@code null},依然返回{@code null}。 * 除去字符串头尾部的空白,如果字符串是{@code null},依然返回{@code null}。
@@ -297,8 +307,9 @@ public class CharSequenceUtil extends StrChecker {
return result; return result;
} }
// endregion
// ------------------------------------------------------------------------ startWith // region ----- startWith
/** /**
* 字符串是否以给定字符开始 * 字符串是否以给定字符开始
@@ -437,8 +448,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return false; return false;
} }
// endregion
// ------------------------------------------------------------------------ endWith // region ----- endWith
/** /**
* 字符串是否以给定字符结尾 * 字符串是否以给定字符结尾
@@ -561,8 +573,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return false; return false;
} }
// endregion
// ------------------------------------------------------------------------ contains // region ----- contains
/** /**
* 指定字符是否在字符串中出现过 * 指定字符是否在字符串中出现过
@@ -761,8 +774,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return true; return true;
} }
// endregion
// ------------------------------------------------------------------------ indexOf // region ----- indexOf
/** /**
* 指定范围内查找指定字符 * 指定范围内查找指定字符
@@ -895,7 +909,7 @@ public class CharSequenceUtil extends StrChecker {
return INDEX_NOT_FOUND; return INDEX_NOT_FOUND;
} }
} }
return new StrFinder(searchStr, ignoreCase).setText(text).start(from); return StrFinder.of(searchStr, ignoreCase).setText(text).start(from);
} }
/** /**
@@ -943,7 +957,7 @@ public class CharSequenceUtil extends StrChecker {
return INDEX_NOT_FOUND; return INDEX_NOT_FOUND;
} }
} }
return new StrFinder(searchStr, ignoreCase) return StrFinder.of(searchStr, ignoreCase)
.setText(text).setNegative(true).start(from); .setText(text).setNegative(true).start(from);
} }
@@ -994,8 +1008,9 @@ public class CharSequenceUtil extends StrChecker {
} while (found < ordinal); } while (found < ordinal);
return index; return index;
} }
// endregion
// ------------------------------------------------------------------------ remove // region ----- remove
/** /**
* 移除字符串中所有给定字符串<br> * 移除字符串中所有给定字符串<br>
@@ -1206,8 +1221,9 @@ public class CharSequenceUtil extends StrChecker {
public static String cleanBlank(final CharSequence str) { public static String cleanBlank(final CharSequence str) {
return filter(str, c -> false == CharUtil.isBlankChar(c)); return filter(str, c -> false == CharUtil.isBlankChar(c));
} }
// endregion
// ------------------------------------------------------------------------ strip // region ----- strip
/** /**
* 去除两边的指定字符串 * 去除两边的指定字符串
@@ -1290,8 +1306,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return str2.substring(from, to); return str2.substring(from, to);
} }
// endregion
// ------------------------------------------------------------------------ add // region ----- add
/** /**
* 如果给定字符串不是以prefix开头的在开头补充 prefix * 如果给定字符串不是以prefix开头的在开头补充 prefix
@@ -1316,8 +1333,9 @@ public class CharSequenceUtil extends StrChecker {
public static String addSuffixIfNot(final CharSequence str, final CharSequence suffix) { public static String addSuffixIfNot(final CharSequence str, final CharSequence suffix) {
return appendIfMissing(str, suffix, suffix); return appendIfMissing(str, suffix, suffix);
} }
// endregion
// ------------------------------------------------------------------------ split // region ----- split
/** /**
* 切分字符串为long数组 * 切分字符串为long数组
@@ -1606,6 +1624,7 @@ public class CharSequenceUtil extends StrChecker {
} }
return array; return array;
} }
// endregion
// region ----- sub // region ----- sub
@@ -2462,7 +2481,7 @@ public class CharSequenceUtil extends StrChecker {
} }
// endregion // endregion
// ------------------------------------------------------------------------ wrap // region ----- wrap
/** /**
* 包装指定字符串<br> * 包装指定字符串<br>
@@ -2679,8 +2698,9 @@ public class CharSequenceUtil extends StrChecker {
return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar; return str.charAt(0) == prefixChar && str.charAt(str.length() - 1) == suffixChar;
} }
// endregion
// ------------------------------------------------------------------------ pad // region ----- pad
/** /**
* 补充字符串以满足指定长度,如果提供的字符串大于指定长度,截断之 * 补充字符串以满足指定长度,如果提供的字符串大于指定长度,截断之
@@ -2802,8 +2822,9 @@ public class CharSequenceUtil extends StrChecker {
return str.toString().concat(repeatByLength(padStr, length - strLen)); return str.toString().concat(repeatByLength(padStr, length - strLen));
} }
// region
// ------------------------------------------------------------------------ center // region ----- center
/** /**
* 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串 * 居中字符串,两边补充指定字符串,如果指定长度小于字符串,则返回原字符串
@@ -2896,18 +2917,7 @@ public class CharSequenceUtil extends StrChecker {
str = padAfter(str, size, padStr); str = padAfter(str, size, padStr);
return str.toString(); return str.toString();
} }
// endregion
// ------------------------------------------------------------------------ str
/**
* {@link CharSequence} 转为字符串null安全
*
* @param cs {@link CharSequence}
* @return 字符串
*/
public static String str(final CharSequence cs) {
return null == cs ? null : cs.toString();
}
// ------------------------------------------------------------------------ count // ------------------------------------------------------------------------ count
@@ -2966,7 +2976,7 @@ public class CharSequenceUtil extends StrChecker {
return count; return count;
} }
// ------------------------------------------------------------------------ compare // region ----- compare
/** /**
* 比较两个字符串,用于排序 * 比较两个字符串,用于排序
@@ -3061,8 +3071,9 @@ public class CharSequenceUtil extends StrChecker {
public static int compareVersion(final CharSequence version1, final CharSequence version2) { public static int compareVersion(final CharSequence version1, final CharSequence version2) {
return VersionComparator.INSTANCE.compare(str(version1), str(version2)); return VersionComparator.INSTANCE.compare(str(version1), str(version2));
} }
// endregion
// ------------------------------------------------------------------------ append and prepend // region ----- append and prepend
/** /**
* 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串<br> * 如果给定字符串不是以给定的一个或多个字符串为结尾,则在尾部添加结尾字符串<br>
@@ -3167,8 +3178,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return prefix.toString().concat(str.toString()); return prefix.toString().concat(str.toString());
} }
// endregion
// ------------------------------------------------------------------------ replace // region ----- replace
/** /**
* 替换字符串中第一个指定字符串 * 替换字符串中第一个指定字符串
@@ -3511,8 +3523,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return builder.toString(); return builder.toString();
} }
// endregion
// ------------------------------------------------------------------------ length // region ----- length
/** /**
* 获取字符串的长度如果为null返回0 * 获取字符串的长度如果为null返回0
@@ -3571,8 +3584,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return sub(string, 0, length) + "..."; return sub(string, 0, length) + "...";
} }
// endregion
// ------------------------------------------------------------------------ firstXXX // region ----- firstXXX
/** /**
* 返回第一个非{@code null} 元素 * 返回第一个非{@code null} 元素
@@ -3614,8 +3628,9 @@ public class CharSequenceUtil extends StrChecker {
public static <T extends CharSequence> T firstNonBlank(final T... strs) { public static <T extends CharSequence> T firstNonBlank(final T... strs) {
return ArrayUtil.firstMatch(StrUtil::isNotBlank, strs); return ArrayUtil.firstMatch(StrUtil::isNotBlank, strs);
} }
// endregion
// ------------------------------------------------------------------------ lower and upper // region ----- lower and upper
/** /**
* 原字符串首字母大写并在其首部添加指定字符串 例如str=name, preString=get =》 return getName * 原字符串首字母大写并在其首部添加指定字符串 例如str=name, preString=get =》 return getName
@@ -3670,8 +3685,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return str.toString(); return str.toString();
} }
// endregion
// ------------------------------------------------------------------------ filter // region ----- filter
/** /**
* 过滤字符串 * 过滤字符串
@@ -3697,8 +3713,9 @@ public class CharSequenceUtil extends StrChecker {
} }
return sb.toString(); return sb.toString();
} }
// endregion
// ------------------------------------------------------------------------ case // region ----- case
/** /**
* 给定字符串中的字母是否全部为大写,判断依据如下: * 给定字符串中的字母是否全部为大写,判断依据如下:
@@ -3713,16 +3730,7 @@ public class CharSequenceUtil extends StrChecker {
* @since 4.2.2 * @since 4.2.2
*/ */
public static boolean isUpperCase(final CharSequence str) { public static boolean isUpperCase(final CharSequence str) {
if (null == str) { return NamingCase.isUpperCase(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;
} }
/** /**
@@ -3738,16 +3746,7 @@ public class CharSequenceUtil extends StrChecker {
* @since 4.2.2 * @since 4.2.2
*/ */
public static boolean isLowerCase(final CharSequence str) { public static boolean isLowerCase(final CharSequence str) {
if (null == str) { return NamingCase.isLowerCase(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;
} }
/** /**
@@ -3764,23 +3763,7 @@ public class CharSequenceUtil extends StrChecker {
* @since 4.3.2 * @since 4.3.2
*/ */
public static String swapCase(final String str) { public static String swapCase(final String str) {
if (isEmpty(str)) { return NamingCase.swapCase(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);
} }
/** /**
@@ -3838,6 +3821,7 @@ public class CharSequenceUtil extends StrChecker {
public static String toCamelCase(final CharSequence name, final char symbol) { public static String toCamelCase(final CharSequence name, final char symbol) {
return NamingCase.toCamelCase(name, symbol); return NamingCase.toCamelCase(name, symbol);
} }
// endregion
// ------------------------------------------------------------------------ isSurround // ------------------------------------------------------------------------ isSurround

View File

@@ -188,4 +188,84 @@ public class NamingCase {
} }
} }
/**
* 给定字符串中的字母是否全部为大写,判断依据如下:
*
* <pre>
* 1. 大写字母包括A-Z
* 2. 其它非字母的Unicode符都算作大写
* </pre>
*
* @param str 被检查的字符串
* @return 是否全部为大写
* @since 4.2.2
*/
public static boolean isUpperCase(final 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;
}
/**
* 给定字符串中的字母是否全部为小写,判断依据如下:
*
* <pre>
* 1. 小写字母包括a-z
* 2. 其它非字母的Unicode符都算作小写
* </pre>
*
* @param str 被检查的字符串
* @return 是否全部为小写
* @since 4.2.2
*/
public static boolean isLowerCase(final 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;
}
/**
* 切换给定字符串中的大小写。大写转小写,小写转大写。
*
* <pre>
* StrUtil.swapCase(null) = null
* StrUtil.swapCase("") = ""
* StrUtil.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
* </pre>
*
* @param str 字符串
* @return 交换后的字符串
* @since 4.3.2
*/
public static String swapCase(final String str) {
if (StrUtil.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) || Character.isTitleCase(ch)) {
buffer[i] = Character.toLowerCase(ch);
} else if (Character.isLowerCase(ch)) {
buffer[i] = Character.toUpperCase(ch);
}
}
return new String(buffer);
}
} }

View File

@@ -12,13 +12,24 @@ import cn.hutool.core.text.CharSequenceUtil;
public class StrFinder extends TextFinder { public class StrFinder extends TextFinder {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* 创建查找器,构造后须调用{@link #setText(CharSequence)} 设置被查找的文本
*
* @param strToFind 查找的字符串
* @param caseInsensitive 是否忽略大小写
* @return {@code StrFinder}
*/
public static StrFinder of(final CharSequence strToFind, final boolean caseInsensitive) {
return new StrFinder(strToFind, caseInsensitive);
}
private final CharSequence strToFind; private final CharSequence strToFind;
private final boolean caseInsensitive; private final boolean caseInsensitive;
/** /**
* 构造 * 构造
* *
* @param strToFind 查找的字符串 * @param strToFind 查找的字符串
* @param caseInsensitive 是否忽略大小写 * @param caseInsensitive 是否忽略大小写
*/ */
public StrFinder(final CharSequence strToFind, final boolean caseInsensitive) { public StrFinder(final CharSequence strToFind, final boolean caseInsensitive) {

View File

@@ -15,18 +15,18 @@ public class LookupReplacer extends StrReplacer {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final Map<String, String> lookupMap; private final Map<String, String> lookupMap;
private final Set<Character> prefixSet; private final Set<Character> keyPrefixSkeyet;
private final int minLength; private final int minLength;
private final int maxLength; private final int maxLength;
/** /**
* 构造 * 构造
* *
* @param lookup 被查找的键值对 * @param lookup 被查找的键值对每个String[]表示一个键值对
*/ */
public LookupReplacer(final String[]... lookup) { public LookupReplacer(final String[]... lookup) {
this.lookupMap = new HashMap<>(); this.lookupMap = new HashMap<>(lookup.length, 1);
this.prefixSet = new HashSet<>(); this.keyPrefixSkeyet = new HashSet<>(lookup.length, 1);
int minLength = Integer.MAX_VALUE; int minLength = Integer.MAX_VALUE;
int maxLength = 0; int maxLength = 0;
@@ -35,7 +35,7 @@ public class LookupReplacer extends StrReplacer {
for (final String[] pair : lookup) { for (final String[] pair : lookup) {
key = pair[0]; key = pair[0];
lookupMap.put(key, pair[1]); lookupMap.put(key, pair[1]);
this.prefixSet.add(key.charAt(0)); this.keyPrefixSkeyet.add(key.charAt(0));
keySize = key.length(); keySize = key.length();
if (keySize > maxLength) { if (keySize > maxLength) {
maxLength = keySize; maxLength = keySize;
@@ -50,7 +50,7 @@ public class LookupReplacer extends StrReplacer {
@Override @Override
protected int replace(final CharSequence str, final int pos, final StringBuilder out) { protected int replace(final CharSequence str, final int pos, final StringBuilder out) {
if (prefixSet.contains(str.charAt(pos))) { if (keyPrefixSkeyet.contains(str.charAt(pos))) {
int max = this.maxLength; int max = this.maxLength;
if (pos + this.maxLength > str.length()) { if (pos + this.maxLength > str.length()) {
max = str.length() - pos; max = str.length() - pos;

View File

@@ -321,7 +321,7 @@ public class SplitUtil {
} else if (0 == text.length()) { } else if (0 == text.length()) {
return ignoreEmpty ? new ArrayList<>(0) : ListUtil.of(StrUtil.EMPTY); return ignoreEmpty ? new ArrayList<>(0) : ListUtil.of(StrUtil.EMPTY);
} }
final SplitIter splitIter = new SplitIter(text, new StrFinder(separator, ignoreCase), limit, ignoreEmpty); final SplitIter splitIter = new SplitIter(text, StrFinder.of(separator, ignoreCase), limit, ignoreEmpty);
return splitIter.toList(isTrim); return splitIter.toList(isTrim);
} }

View File

@@ -74,7 +74,7 @@ public class SplitIterTest {
final String str1 = "a, ,,efedsfs, ddf,"; final String str1 = "a, ,,efedsfs, ddf,";
final SplitIter splitIter = new SplitIter(str1, final SplitIter splitIter = new SplitIter(str1,
new StrFinder("e", false), StrFinder.of("e", false),
Integer.MAX_VALUE, Integer.MAX_VALUE,
true true
); );
@@ -141,7 +141,7 @@ public class SplitIterTest {
public void splitByEmptyTest(){ public void splitByEmptyTest(){
final String text = "aa,bb,cc"; final String text = "aa,bb,cc";
final SplitIter splitIter = new SplitIter(text, final SplitIter splitIter = new SplitIter(text,
new StrFinder("", false), StrFinder.of("", false),
3, 3,
false false
); );