学习编程的一个比较好的方法就是阅读别人优秀的代码,学习别人的代码并尝试自己去实现那些功能,这样对提升自己的编码能力是有十分大的帮助的。这里简单实现一个不依赖于其他库的strutil库。
为了使代码更加健壮,一般需要统一处理一下异常的输入,这样在接收异常的输入时,程序不至于直接崩溃掉,由于是工具类,所以私有化构造方法,并将各种实现方法以静态方法的形式实现。
public class StrUtil {
private static final String[] EMPTY_ARRAY = new String[0];
private static final Supplier<String> NULL_STRING_MSG = () -> "字符串不能为空";
private static final Predicate<String> NULL_STRING_PREDICATE = Objects::isNull;
/**
* 私有化构造方法
*/
private StrUtil(){
}
/**
* 验证输入
* @param value
* @param predicate
* @param supplier
*/
private static void validate(String value, Predicate<String> predicate, final Supplier<String> supplier){
if(predicate.test(value)){
throw new IllegalArgumentException(supplier.get());
}
}
/**
* 验证输入是否为空或者空字符串
* @param value
* @return
*/
private static boolean isNullOrEmpty(String value){
return value == null || value.isEmpty();
}
}
private static String appendArray(String value, final String[] appends){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(appends == null || appends.length == 0){
return value;
}
StringJoiner joiner = new StringJoiner(""); // 添加字符串时,以""为分割符
for(String append : appends){
joiner.add(append);
}
return value + joiner.toString();
}
/**
* 将字符串数组中的值添加到字符串后
* @param value
* @param appends
* @return
*/
public static String append(String value, final String... appends){
return appendArray(value, appends);
}
/**
* 获取指定的两个字符串之间的字符串
* @param value
* @param start
* @param end
* @return
*/
public static String[] between(String value, final String start, final String end){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
validate(start, NULL_STRING_PREDICATE, () -> "start不能为空");
validate(end, NULL_STRING_PREDICATE, () -> "end不能为空");
String[] parts = value.split(end);
return Arrays.stream(parts)
.filter(subPart -> subPart.contains(start))
.map(subPart -> subPart.substring(subPart.indexOf(start) + start.length()))
.toArray(String[]::new);
}
/**
* 将字符串转化成字符串数组 "123" -> ["1", "2", "3"]
* @param value
* @return
*/
public static String[] chars(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.split("");
}
/**
* 将字符串中的空白字符全部替换成一个空格
* @param value
* @return
*/
public static String collapseWhitespace(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.trim().replaceAll("\\s\\s+", " ");
}
/**
* 判断子串是否包含在字符串中
* @param value
* @param sub
* @param caseSensitive
* @return
*/
private static boolean contains(String value, final String sub, final boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(caseSensitive){
return value.contains(sub);
}
return value.toLowerCase().contains(sub.toLowerCase());
}
/**
* 判断子串是否包含在字符串中,默认忽略大小写
* @param value
* @param sub
* @return
*/
public static boolean contains(String value, final String sub){
return contains(value, sub, false);
}
/**
* 判断所有的子串是否都包含在字符串中
* @param value
* @param subs
* @param caseSensitive
* @return
*/
private static boolean containsAll(String value, final String[] subs, final boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return Arrays.stream(subs).allMatch(sub -> contains(value, sub, caseSensitive));
}
/**
* 判断所有的子串是否都包含在字符串中,默认忽略大小写
* @param value
* @param subs
* @return
*/
public static boolean containsAll(String value, final String[] subs){
return containsAll(value, subs, false);
}
/**
* 判断一个或者多个子串包含在字符串中
* @param value
* @param subs
* @param caseSensitive
* @return
*/
public static boolean containsAny(String value, final String[] subs, final boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return Arrays.stream(subs).anyMatch(sub -> contains(value, sub, caseSensitive));
}
/**
* 判断一个或者多个子串包含在字符串中,默认忽略大小写
* @param value
* @param subs
* @return
*/
public static boolean containsAny(String value, final String[] subs){
return containsAny(value, subs);
}
public static long countSubstr(String value, final String sub, boolean allowOverlapping, long count){
int position = value.indexOf(sub);
if(position == -1){
return count;
}
int offset;
// 是否完整越过子串
if(!allowOverlapping){
offset = position + sub.length();
}else{
offset = position + 1;
}
return countSubstr(value.substring(offset), sub, allowOverlapping, ++count);
}
public static long countSubstr(String value, final String sub, final boolean caseSensitive, boolean allowOverLapping){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return countSubstr(caseSensitive ? value : value.toLowerCase(), caseSensitive ? sub : sub.toLowerCase(),
allowOverLapping, 0L);
}
/**
* 统计一个子串在字符串中出现的次数,默认区分大小写,默认统计一次越过真个子串
* @param value
* @param sub
* @return
*/
public static long countSubstr(String value, final String sub){
return countSubstr(value, sub, true, false);
}
public static boolean endsWith(String value, final String sub, final boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
int remainingLength = value.length() - sub.length();
if(caseSensitive){
return value.indexOf(sub, remainingLength) > -1;
}
return value.toLowerCase().indexOf(sub.toLowerCase(), remainingLength) > -1;
}
/**
* 判断字符串是否一某个子串结尾,默认忽略大小写
* @param value
* @param sub
* @return
*/
public static boolean endsWith(String value, final String sub){
return endsWith(value, sub, false);
}
public static String ensureStart(String value, final String prefix, final boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(caseSensitive){
return value.startsWith(prefix) ? value : prefix + value;
}
return value.toLowerCase().startsWith(prefix.toLowerCase()) ? value.toLowerCase() : prefix.toLowerCase() + value.toLowerCase();
}
/**
* 确认字符串以一个子串开头,如果不是则将子串添加到字符串头部,默认区分大小写
* @param value
* @param prefix
* @return
*/
public static String ensureStart(String value, final String prefix){
return ensureStart(value, prefix, true);
}
/**
* 以utf-8编码字符串
* @param value
* @return
*/
public static String base64Encode(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return Base64.getEncoder().encodeToString(value.getBytes(StandardCharsets.UTF_8));
}
/**
* 解码
* @param value
* @return
*/
public static String base64Decode(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return new String(Base64.getDecoder().decode(value), StandardCharsets.UTF_8);
}
public static Optional<String> first(String value, final int n){
return Optional.ofNullable(value).filter(v -> !v.isEmpty()).map(v -> v.substring(0, n));
}
/**
* 返回字符串的第一个子串
* @param value
* @return
*/
public static Optional<String> head(String value){
return first(value, 1);
}
/**
* 返回字符串的最后一个子串,确保一定返回一个对象
* @param value
* @return
*/
public static Optional<String> tail(String value){
return Optional.ofNullable(value).filter(v -> !v.isEmpty()).map(v -> last(v, v.length() - 1));
}
/**
* 判断子串从指定得到位置起,是否包含在字符串中
* @param value
* @param sub
* @param offset
* @param caseSensitive
* @return
*/
public static int indexOf(String value, final String sub, int offset, boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(caseSensitive){
return value.indexOf(sub, offset);
}
return value.toLowerCase().indexOf(sub.toLowerCase(), offset);
}
/**
* 将子串插入到字符串指定的位置
* @param value
* @param sub
* @param index
* @return
*/
public static String insert(String value, String sub, int index){
validate(value, NULL_STRING_PREDICATE,NULL_STRING_MSG);
validate(sub, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(index > value.length()){
return value;
}
return append(value.substring(0, index), sub, value.substring(index));
}
/**
* 检验一个字符串全是大写字母
* @param value
* @return
*/
public static boolean isUpperCase(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
for(int i = 0; i < value.length(); i++){
if(Character.isLowerCase(value.charAt(i))){
return false;
}
}
return true;
}
/**
* 检验一个字符串全是小写字母
* @param value
* @return
*/
public static boolean isLowerCase(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
for(int i = 0; i < value.length(); i++){
if(Character.isUpperCase(value.charAt(i))){
return false;
}
}
return true;
}
/**
* 返回最后的n个字符串
* @param value
* @param n
* @return
*/
public static String last(String value, int n){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(n > value.length()){
return value;
}
return value.substring(value.length() - n);
}
/**
* 将字符串重复multiplier次
* @param value
* @param multiplier
* @return
*/
public static String repeat(String value, final int multiplier){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return Stream.generate(() -> value).limit(multiplier).collect(Collectors.joining());
}
/**
* 在字符串末尾填充多个pad
* @param value
* @param pad
* @param length
* @return
*/
public static String rightPad(String value, String pad, int length){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
validate(pad, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(value.length() > length){
return value;
}
return append(value, repeat(pad, length - value.length()));
}
/**
* 在字符串头部填充多个pad
* @param value
* @param pad
* @param length
* @return
*/
public static String leftPad(String value, String pad, int length){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
validate(pad, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(value.length() > length){
return value;
}
return append(repeat(pad, length - value.length()), value);
}
/**
* 判断一个对象是否为字符串
* @param value
* @return
*/
public static boolean isString(Object value){
if(Objects.isNull(value)){
throw new IllegalArgumentException("字符串不能为空");
}
return value instanceof String;
}
/**
* 去除左侧的空格
* @param value
* @return
*/
public static String leftTrim(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.replaceAll("^\\s+", "");
}
/**
* 去除右侧的空格
* @param value
* @return
*/
public static String rightTrim(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.replaceAll("\\s+$", "");
}
/**
* 去除左侧右侧的空格
* @param value
* @return
*/
public static String trim(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return leftTrim(rightTrim(value));
}
/**
* 获取字符串的长度
* @param value
* @return
*/
public static int length(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.length();
}
public static String prependArray(String value, String[] prepends){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(prepends == null || prepends.length == 0){
return value;
}
StringJoiner joiner = new StringJoiner("");
for(String prepend : prepends){
joiner.add(prepend);
}
return joiner.toString() + value;
}
/**
* 在字符串的前端添加字符串
* @param value
* @param prepends
* @return
*/
public static String prepend(String value, String... prepends){
return prepend(value, prepends);
}
/**
* 去除字符串数组中的字符串
* @param strings
* @return
*/
public static String[] removeEmptyStrings(String[] strings){
if(Objects.isNull(strings)){
throw new IllegalArgumentException("字符数组不能为空");
}
return Arrays.stream(strings).filter(str -> str != null && !str.trim().isEmpty()).toArray(String[]::new);
}
public static String removeLeft(String value, String prefix, boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE`, NULL_STRING_MSG);
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
if(caseSensitive){
return value.startsWith(prefix) ? value.substring(prefix.length()) : value;
}
return value.toLowerCase().startsWith(prefix.toLowerCase()) ? value.substring(prefix.length()) : value;
}
/**
* 删除字符串的子串前缀, 默认区分大下写
* @param value
* @param prefix
* @return
*/
public static String removeLeft(String value, String prefix){
return removeLeft(value, prefix, true);
}
public static String removeRight(String value, String suffix, boolean caseSensitive){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return endsWith(value, suffix, caseSensitive) ? value.substring(0, value.toLowerCase().lastIndexOf(suffix.toLowerCase(Locale.ROOT))) : value;
}
/**
* 删除字符串的子串后缀
* @param value
* @param suffix
* @return
*/
public static String removeRight(String value, String suffix){
return removeRight(value, suffix,true);
}
/**
* 删除字符串中所有的非字母的字符
* @param value
* @return
*/
public static String removeNoWords(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.replaceAll("[^\\w]+", "");
}
/**
* 删除字符串中所有的空格
* @param value
* @return
*/
public static String removeSpaces(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.replaceAll("\\s", "");
}
/**
* 反转字符串
* @param value
* @return
*/
public static String reverse(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return new StringBuilder(value).reverse().toString();
}
public static String[] words(String value, String delimiter){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.split(delimiter);
}
/**
* 分割字符串为字符串数组,默认以空白分割
* @param value
* @return
*/
public static String[] words(String value){
return words(value, "\\s+");
}
/**
* 随机打乱字符串各位置的值
* @param value
* @return
*/
public static String shuffle(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
String[] chars = chars(value);
Random random = new Random();
for(int i = 0; i < chars.length; i++){
int r = random.nextInt(chars.length);
String tmp = chars[i];
chars[i] = chars[r];
chars[r] = tmp;
}
return Arrays.stream(chars).collect(Collectors.joining());
}
/**
* 获取begin到end之间的字符串
* @param value
* @param begin
* @param end
* @return
*/
public static String slice(String value, int begin, int end){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return value.substring(begin, end);
}
/**
* 替换字符串中的非法字符
* @param value
* @return
*/
public static String transliterate(String value){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
String res = value;
Set<Map.Entry<String, List<String>>> entries = Ascii.ascii.entrySet();
for(Map.Entry<String, List<String>> entry : entries){
for(String ch : entry.getValue()){
res = res.replace(ch, entry.getKey());
}
}
return res;
}
/**
* 在字符串前后填充子串
* @param value
* @param prefix
* @param suffix
* @return
*/
public static String surround(String value, String prefix, String suffix){
validate(value, NULL_STRING_PREDICATE, NULL_STRING_MSG);
return append(Optional.ofNullable(prefix).orElse(""), value, Optional.ofNullable(suffix).orElse(""));
}
点击install,即可将该项目安装到本地仓库。在本地仓库也可以看到我们的jar包,这样以后就可以使用这个简单的str工具库库了,当然以后还可以不断完善扩充工具库。
创建一个demo的maven项目,引入我们的坐标。
当然,也可以创建一个sonatype账号,将自己的maven项目上传到maven中央仓库,让别人也能使用自己的maven项目,这个demo远没有达到能上传中央仓库的层度,所以这里就不介绍具体操作了,感兴趣的可以自行搜索一下步骤,很简单的。