StringUtils

StringUtils

对String功能的补充(null安全)包括查询 判断 截取 去除 分组 替换 等功能,又加入各种简明的关键词对功能进行加强,大部分功能都很简单,实现的种类也很齐全

关键词:

Not:boolean求反

Empty:空对象   Empty,空对象,拥有null的意义却没有null的bug

NULL:null       Null,关键字,跟绝大多数bug沾亲带故

Start:字符串开头

End:字符串结尾

Whitespace:空格,包含全角,半角以及各种带有空格的操作码(/t。。)

IgnoreCase:忽视大小写

last:最后一位

Any:将String转为char[]后中的任意一个

But:对其他关键字取反

Only:仅仅

None:取反

Between:有left 有right就有可能有Between

代码版本:apache.commons.lang3.0

1.判断

isEmpty:判断是否为空

isBlank:是否空白

countMatches(CharSequence str, CharSequence sub):匹配次数

isAlpha:仅包括字符(Alpha为字母,不过本地话以后可以理解为字符)

isAlphaSpace:允许为半角空格

isAlphanumeric:允许为数字

isAlphanumericSpace,isAsciiPrintable,isNumeric,isNumericSpace,isWhitespace,isAllLowerCase,isAllUpperCase等

contains,equal 等

    public static boolean isEmpty(CharSequence cs) {//3.0之前为String
        return cs == null || cs.length() == 0;
    }//实现CharSequence 接口的有CharBuffer、String、StringBuffer、StringBuilder
    public static boolean isBlank(CharSequence cs) {
        int strLen;
        if (cs == null || (strLen = cs.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if (Character.isWhitespace(cs.charAt(i)) == false) {
                return false;
            }
        }
        return true;
    }
... 
for (int i = 0; i < sz; i++) {
            if (Character.isLetter(cs.charAt(i)) == false) { //简单的理解为字母+方言(比如中文)
                return false;
            }
        }
...//isAlphaSpace
if (Character.isLetter(cs.charAt(i)) == false && cs.charAt(i) != ' ') {//半角空格
                return false;
            }
...//isNumeric
for (int i = 0; i < sz; i++) {
            if (Character.isDigit(cs.charAt(i)) == false) { //循环判断数字,故带+/-/.的全pass,另外大多判断都是如此
                    return false;                           //,故加入特殊方法
            }
        }

补充:半角空格与全角空格字节码不一样,trim直接与半角空格作比较(val[off + st] <= ' '),即与assic码比较

         isWhitespace则做了更多的判断,总之,结论如下

1.Character.isWhitespace() 全角和半角空格都为空格,即返回true
2.Character.isSpaceChar()  全角和半角空格都为空格,即返回true
3.Character.isSpace() 半角空格为空格,即半角空格返回true,全角空格返回false,但此方法被废弃
4.trim()只截取掉半角的空格(全角空格与编码有关,估计当时只有assic上哪几种空格表示方式)

2特殊去除,通常仅代表两端

trim:非空判断后,去除前后空格(半角)

strip(String str, String stripChars):去除(剥夺)字符串某(两)端给定字符(默认为null)

stripStart / stripEnd

stripAccents:去"重音",关系不大

chomp:去除str尾部的换行符,属于截串的特殊方法

chop:去除最后一个字符+去除str尾部的换行符

补充:1967年公布的assic码(美国信息互换标准代码)是7位编码,包括95个图形字符+33个控制字符,主要用在电传打字机上,后来成为了计算机 上最重要的标准,由于太偏向M帝,面对那些以英语为主要语言的国家,竟然不太适合,英镑,西欧的重音符都无法表示,好在计算机是以八位存储字符的,故有了 第八位拓展,再然后就有了unicode,而unicode改变了一个字节代表1字符的关系,一本书,一段字符的大小,也不再仅仅由字符的多少决定 了。。。

    public static String trim(String str) {
        return str == null ? null : str.trim();
    }//null安全
    public static String stripStart(String str, String stripChars) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return str;
        }
        int start = 0;
        if (stripChars == null) {
            while (start != strLen && Character.isWhitespace(str.charAt(start))) {//null就是去空格
                start++;
            }
        } else if (stripChars.length() == 0) {
            return str;
        } else {
//可见去除的是连续存在stripChars中的字符
while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) { start++; } } return str.substring(start); }
...   //chomp
int lastIdx = str.length() - 1;
        char last = str.charAt(lastIdx);
        if (last == CharUtils.LF) {
            if (str.charAt(lastIdx - 1) == CharUtils.CR) { //

                lastIdx--;
            }
        } else if (last != CharUtils.CR) {
            lastIdx++;
        }
        return str.substring(0, lastIdx);
...//chop 
 if (strLen < 2) {
            return EMPTY;
        }
int lastIdx = strLen - 1;
        String ret = str.substring(0, lastIdx);
        char last = str.charAt(lastIdx);
        if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
            return ret.substring(0, lastIdx - 1);
        }
        return ret;

3.查询:

indexOf系列,包括indexOfIgnoreCase  lastIndexOf   lastIndexOfIgnoreCase lastIndexOfAny indexOfAnyBut
ordinalIndexOf :对indexOf的拓展,获取匹配字符串指定次数的索引

4.截取

substring(String str, int start, int end):截取字符串,参数为索引

包括substringBefore   substringAfter  substringBeforeLast  substringAfterLast

left / right / mid(String str, int pos, int len):参数为len

//可以发现实现上对于不正确的数据直接抛异常,而调用则通过中间层(工具类)来排除错误
//,另外,beginIndex为索引,而    endIndex为ex索引(索引+1),或者是算头不算尾
public static String substring(String str, int start) { if (str == null) { return null; } // handle negatives, which means last n characters if (start < 0) { start = str.length() + start; // remember start is negative } if (start < 0) { start = 0; } if (start > str.length()) { return EMPTY; } return str.substring(start); }
    public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
    }
//mid left right
str.substring(str.length() - len);//right str.substring(pos, pos + len);//mid str.substring(0, len);//left
   public static String substringBefore(String str, String separator) {
        if (isEmpty(str) || separator == null) {
            return str;
        }
        if (separator.length() == 0) {
            return EMPTY;
        }
        int pos = str.indexOf(separator);//获取第一个指定字符前所有字符
        if (pos == INDEX_NOT_FOUND) {
            return str;
        }
        return str.substring(0, pos);
    }

5.分组

split:匹配任意字符进行分组  (不同于String.split)

splitByWholeSeparator:匹配全部字符,可以连续匹配

splitPreserveAllTokens:同上,但不能连续匹配

splitByCharacterType:根据Character类型进行匹配

splitByCharacterTypeCamelCase:同上,支持驼峰

String.split:通过Pattern(正则表达式的编译表示形式)实现

栗子:

StringUtils.split("split","pi");//{s,l,t}
StringUtils.splitByWholeSeparator("1   2  "," ");//{1,2,}
StringUtils.splitPreserveAllTokens("1   2  "," ");//{1,,,2,,}
StringUtils.splitByCharacterType("splitByCharacterTypeCamelCase");//{split,B,y,C,haracter,T,ype,C,amel,C,ase}    
StringUtils.splitByCharacterTypeCamelCase("splitByCharacterTypeCamelCase");//{split,By,Character,Type,Camel,Case}
    

关键源码:

 ...//split
if (separatorChars.indexOf(str.charAt(i)) >= 0) {//字符串str.charAt(i),是否存在separatorChars中判断 ...
...//splitByWholeSeparator  splitPreserveAllTokens
while (end < len) { end = str.indexOf(separator, beg);//跟split相反,为全匹配 if (end > -1) { if (end > beg) { numberOfSubstrings += 1; if (numberOfSubstrings == max) { //max为分组限制 end = len; substrings.add(str.substring(beg)); } else { //通常添加 substrings.add(str.substring(beg, end)); beg = end + separatorLength; } } else { if (preserveAllTokens) { //连续匹配处理  numberOfSubstrings += 1;
                        if (numberOfSubstrings == max) {
                            end = len;
                            substrings.add(str.substring(beg));
                        } else {
                            substrings.add(EMPTY);
                        } } beg
= end + separatorLength; } } else {//最后一组 substrings.add(str.substring(beg)); end = len; } }
...//splitByCharacterType    splitByCharacterTypeCamelCase
int type = Character.getType(c[pos]);//判断类型 ...if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) { int newTokenStart = pos - 1; if (newTokenStart != tokenStart) { list.add(new String(c, tokenStart, newTokenStart - tokenStart)); tokenStart = newTokenStart; } } else { list.add(new String(c, tokenStart, pos - tokenStart)); tokenStart = pos; } currentType = type;

6. 合并

 join:分组的反操作

System.out.println(StringUtils.join(new String[]{"j","o","i","n"},"-"));//j-o-i-n
System.out.println(StringUtils.join(Arrays.asList(null,"j",null,"o","i","n",null),"-"));//-j--o-i-n-
  
...  for (int i = startIndex; i < endIndex; i++) {
   if (i > startIndex) {
     buf.append(separator);
      }
   if (array[i] != null) { //null就是 ""
     buf.append(array[i]);
      }
    }
return buf.toString();

7.删除:先进行对应查询在截串

deleteWhitespace :去除各种空格  

removeStart(removeStartIgnoreCase):当第一段字符为匹配字符时,去除 

removeEnd(removeEndIgnoreCase):当最后一段字符为匹配字符时,去除

remove:删除匹配到的全部字符

System.out.println(StringUtils.deleteWhitespace("A B    c a b    C "));//ABcabC
System.out.println(StringUtils.removeStart("ABcacbC","a"));//ABcacbC
System.out.println(StringUtils.removeStartIgnoreCase("ABcacbC","a"));//BcacbC
System.out.println(StringUtils.removeEnd("ABcacbC","c"));//ABcacbC
System.out.println(StringUtils.removeEndIgnoreCase("ABcacbC","c"));//ABcacb
System.out.println(StringUtils.remove("ABcacbC","c"));//ABabC

8.替换

replaceOnce:替换第一个合格规定的

replace:替换所有合格规定的

replaceEach:参数为数组且一一对应,包含输入参数不等判断

replaceEachRepeatedly:replaceEach的迭代

replaceChars:replaceEach的字符版

overlay(String str, String overlay, int start, int end):所需参数不一样,可以变插入

 System.out.println(StringUtils.replaceOnce("abABab", "a","1"));//1bABab
 System.out.println(StringUtils.replace("abABab", "a","1"));//1bAB1b
 StringUtils.replaceEach("ABB", new String[]{"AB"},new String[]{"A"});//AB
 StringUtils.replaceEachRepeatedly("ABb", new String[]{"AB","b"},new String[]{"A","B"});//A System.out.println(StringUtils.replaceChars("abABab",'a','1'));//1bAB1b System.out.println(StringUtils.replaceChars("abABab ","ab","12"));//12AB12
System.out.println(StringUtils.overlay("abcdefg","一二三",1,2));//a一二三cdefg
...//replaceOnce 与 replace
while (end != INDEX_NOT_FOUND) {
   buf.append(text.substring(start, end)).append(replacement);
   start = end + replLength;
   if (--max == 0) {    //替换次数,replaceOnce为1,replace为-1
      break;
     end = text.indexOf(searchString, start);
        }
  buf.append(text.substring(start));
...

9.添加

repeat:循环

leftPad /rightPad/center :补齐最低字符数 (中文,英文与字符是一比一的关系,但宽度不一样,需要特殊处理)

System.out.println(StringUtils.rightPad("xx", 5, "阿"));//xx阿阿阿
System.out.println(StringUtils.rightPad("xx", 5, "a"));//xxaaa
System.out.println(StringUtils.center ("xx", 5, "a"));//axxaa

 10.转换,多为去null后直接调用String

upperCase:大写

lowerCase:小写

capitalize:首字母大写

uncapitalize:首字母小写

swapCase:大小写互转

reverse:倒叙

reverseDelimited:先分组,在倒叙

abbreviate(String str, int offset, int maxWidth):缩写写法,超出长度用...补齐很有用(缺点同补齐)

abbreviateMiddle(String str, String middle, int length):中间替换

   public static String capitalize(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return str;
        }
        return new StringBuilder(strLen)
            .append(Character.toTitleCase(str.charAt(0))) //只有首字母- -
            .append(str.substring(1))
            .toString();
    }
...//uncapitalize
 return new StringBuilder(strLen)
            .append(Character.toLowerCase(str.charAt(0))) //转换大小要谨慎,小写随意,当然,与我们无关
            .append(str.substring(1))
            .toString();

特殊

--Difference

difference(String str1, String str2):去除str2中与str1相同的地方

indexOfDifference(CharSequence cs1, CharSequence cs2):获取两处第一次不同的索引

indexOfDifference(CharSequence... css):数组版

getCommonPrefix(String... strs):获取相同字符-->indexOfDifference+截串

--其他

int getLevenshteinDistance(CharSequence s, CharSequence t):计算相似度,理论时间到了- -

LevenshTeinDistance是俄罗斯科学家Vladimir Levenshtein在1965年提出的根据编辑距离(Edit Distance)计算字符串相似度的一种算法。

原文地址:https://www.cnblogs.com/liuCy/p/3494813.html