This commit is contained in:
Looly 2023-03-25 15:22:58 +08:00
parent 8ae651caed
commit 611db9a56b
2 changed files with 114 additions and 89 deletions

View File

@ -303,53 +303,6 @@ public class CharSequenceUtil extends StrChecker {
return c == str.charAt(0);
}
/**
* 是否以指定字符串开头<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @param ignoreCase 是否忽略大小写
* @return 是否以指定字符串开头
* @since 5.4.3
*/
public static boolean startWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
return startWith(str, prefix, ignoreCase, false);
}
/**
* 是否以指定字符串开头<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false<br>
* <pre>
* CharSequenceUtil.startWith("123", "123", false, true); -- false
* CharSequenceUtil.startWith("ABCDEF", "abc", true, true); -- true
* CharSequenceUtil.startWith("abc", "abc", true, true); -- false
* </pre>
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @param ignoreCase 是否忽略大小写
* @param ignoreEquals 是否忽略字符串相等的情况
* @return 是否以指定字符串开头
* @since 5.4.3
*/
public static boolean startWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase, final boolean ignoreEquals) {
if (null == str || null == prefix) {
if (ignoreEquals) {
return false;
}
return null == str && null == prefix;
}
final boolean isStartWith = str.toString()
.regionMatches(ignoreCase, 0, prefix.toString(), 0, prefix.length());
if (isStartWith) {
return (false == ignoreEquals) || (false == equals(str, prefix, ignoreCase));
}
return false;
}
/**
* 是否以指定字符串开头
*
@ -426,6 +379,41 @@ public class CharSequenceUtil extends StrChecker {
}
return false;
}
/**
* 是否以指定字符串开头<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @param ignoreCase 是否忽略大小写
* @return 是否以指定字符串开头
* @since 5.4.3
*/
public static boolean startWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
return startWith(str, prefix, ignoreCase, false);
}
/**
* 是否以指定字符串开头<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false<br>
* <pre>
* CharSequenceUtil.startWith("123", "123", false, true); -- false
* CharSequenceUtil.startWith("ABCDEF", "abc", true, true); -- true
* CharSequenceUtil.startWith("abc", "abc", true, true); -- false
* </pre>
*
* @param str 被监测字符串
* @param prefix 开头字符串
* @param ignoreCase 是否忽略大小写
* @param ignoreEquals 是否忽略字符串相等的情况
* @return 是否以指定字符串开头
* @since 5.4.3
*/
public static boolean startWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase, final boolean ignoreEquals) {
return new StrRegionMatcher(ignoreCase, ignoreEquals, true)
.test(str, prefix);
}
// endregion
// region ----- endWith
@ -444,48 +432,6 @@ public class CharSequenceUtil extends StrChecker {
return c == str.charAt(str.length() - 1);
}
/**
* 是否以指定字符串结尾<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @param ignoreCase 是否忽略大小写
* @return 是否以指定字符串结尾
*/
public static boolean endWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
return endWith(str, suffix, ignoreCase, false);
}
/**
* 是否以指定字符串结尾<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @param ignoreCase 是否忽略大小写
* @param ignoreEquals 是否忽略字符串相等的情况
* @return 是否以指定字符串结尾
* @since 5.8.0
*/
public static boolean endWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase, final boolean ignoreEquals) {
if (null == str || null == suffix) {
if (ignoreEquals) {
return false;
}
return null == str && null == suffix;
}
final int strOffset = str.length() - suffix.length();
final boolean isEndWith = str.toString()
.regionMatches(ignoreCase, strOffset, suffix.toString(), 0, suffix.length());
if (isEndWith) {
return (false == ignoreEquals) || (false == equals(str, suffix, ignoreCase));
}
return false;
}
/**
* 是否以指定字符串结尾
*
@ -551,6 +497,35 @@ public class CharSequenceUtil extends StrChecker {
}
return false;
}
/**
* 是否以指定字符串结尾<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @param ignoreCase 是否忽略大小写
* @return 是否以指定字符串结尾
*/
public static boolean endWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
return endWith(str, suffix, ignoreCase, false);
}
/**
* 是否以指定字符串结尾<br>
* 如果给定的字符串和开头字符串都为null则返回true否则任意一个值为null返回false
*
* @param str 被监测字符串
* @param suffix 结尾字符串
* @param ignoreCase 是否忽略大小写
* @param ignoreEquals 是否忽略字符串相等的情况
* @return 是否以指定字符串结尾
* @since 5.8.0
*/
public static boolean endWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase, final boolean ignoreEquals) {
return new StrRegionMatcher(ignoreCase, ignoreEquals, false)
.test(str, suffix);
}
// endregion
// region ----- contains

View File

@ -0,0 +1,50 @@
package cn.hutool.core.text;
import java.io.Serializable;
import java.util.function.BiPredicate;
/**
* 字符串区域匹配器用于匹配字串是头部匹配还是尾部匹配
*
* @author looly
* @since 6.0.0
*/
public class StrRegionMatcher implements BiPredicate<CharSequence, CharSequence>, Serializable {
private static final long serialVersionUID = 1L;
private final boolean ignoreCase;
private final boolean ignoreEquals;
private final boolean isPrefix;
/**
* 构造
*
* @param ignoreCase 是否忽略大小写
* @param ignoreEquals 是否忽略字符串相等的情况
* @param isPrefix {@code true}表示检查开头匹配{@code false}检查末尾匹配
*/
public StrRegionMatcher(final boolean ignoreCase, final boolean ignoreEquals, final boolean isPrefix) {
this.ignoreCase = ignoreCase;
this.ignoreEquals = ignoreEquals;
this.isPrefix = isPrefix;
}
@Override
public boolean test(final CharSequence str, final CharSequence strToCheck) {
if (null == str || null == strToCheck) {
if (ignoreEquals) {
return false;
}
return null == str && null == strToCheck;
}
final int toffset = isPrefix ? 0 : str.length() - strToCheck.length();
final boolean matches = str.toString()
.regionMatches(ignoreCase, toffset, strToCheck.toString(), 0, strToCheck.length());
if (matches) {
return (false == ignoreEquals) || (false == StrUtil.equals(str, strToCheck, ignoreCase));
}
return false;
}
}