String的split方法的使用

1.引言
split方法很常用,記得我入職公司的時候,第一道筆試題就是關(guān)于字符串的拆分拼裝等,這也足以說明,大公司對這些方法的重視程度.
其實我們平時一般用到的都是這些方法最簡單的用法,但如果你不了解他的實現(xiàn)原理,碰到某些特殊問題終究是會被卡住的,于是就產(chǎn)生了所謂的bug,而這也就是大神和菜鳥的區(qū)別之一吧.廣度是一方面,但真正看一個程序員是不是牛逼,重要的還是看他的深度,比如這個split的用法,如果你還停留在簡單的用法上,不妨看看后面,也看看你的深度,與君共勉!
2.split用法
先上一個例子:
1.最普通的用法
String str1 = "aa,bb";
String[] split1 = str1.split(",");
System.out.println(split1.length);
//這個結(jié)果是2,都知道的
2.比較普通的用法
String str2 = "";
String[] split2 = str2.split(",");
System.out.println(split2.length);
//這個結(jié)果是1,但部分人會認為這個的結(jié)果是0,
//這個為什么是1,我會在后面說
3.看起來比較奇怪的用法
String str3 = ",";
String[] split3 = str3.split(",");
System.out.println(split3.length);
//這個結(jié)果是0,但部分人會認為結(jié)果是1,部分人會認為結(jié)果是2.
//這個又為什么是0,我也會在后面說
3.split源碼分析
split方法準確的來說有兩個參數(shù)(String regex, int limit),只不過平時我們用的,是split的一個重載方法(String regex),默認是把第二個參數(shù)設(shè)置為0,源碼如下:
public String[] split(String regex) {
return split(regex, 0);
}
public String[] split(String regex, int limit) {
具體實現(xiàn)...
}
3.1.參數(shù)解釋—regex
1.如果表達式不匹配輸入的任何內(nèi)容,返回的數(shù)組只具有一個元素,即此字符串。(尤其注意空字符串這種情況,他也是一個字符串)
2.可以匹配的情況下,每一個字符串都由另一個匹配給定表達式的子字符串終止,或者由此字符串末尾終止(數(shù)組中的字符串按照他們在此字符串出現(xiàn)的順序排列)
3.2.參數(shù)解釋—limit
該參數(shù)用于控制模式匹配使用的次數(shù),可以影響到數(shù)組的長度
1.limit>0:
模式匹配將被最多應(yīng)用n-1次,數(shù)組的長度將不會大于n,數(shù)組的最后一項將包含所有超出最后匹配的定界符的輸入。
2.limit<0:
模式匹配將應(yīng)用盡可能多的次數(shù),而且數(shù)組的長度是任何長度。
3.lilmit=0:
模式匹配將被應(yīng)用盡可能多的次數(shù),數(shù)組可以是任何長度,并且結(jié)尾空字符串將被丟棄。
3.3.不同limit值的情況下的split結(jié)果驗證
假設(shè)有字符串a(chǎn)a,bcd,eef,
3.3.1.limit=0,regex=","
尾部的逗號,直接被忽略,頭部的逗號不會忽略
String line = ",aa,bcd,eef,,,";
String[] split = line.split(",",0);
System.out.println(split.length);//4
3.3.2.limit=2,regex=","
總長度被限制成最大2個
String line = ",aa,bcd,eef,,,";
String[] split = line.split(",",2);
System.out.println(split.length);//2
3.3.3.limit=100,regex=","
總長度被限制成最大100個
但結(jié)果是7個,說明當limit大于0,并且遠大于應(yīng)該有的長度時,頭部和尾部的逗號都沒有被忽略
String line = ",aa,bcd,eef,,,";
String[] split = line.split(",",100);
System.out.println(split.length);//7
3.3.4.limit=-1,regex=","
結(jié)果是7個,說明當limit小于0時,頭部和尾部的逗號都沒有被忽略
String line = ",aa,bcd,eef,,,";
String[] split = line.split(",",100);
System.out.println(split.length);//7
4.擴展
在java.lang包中有String.split()方法的原型是:
public String[] split(String regex, int limit)
split函數(shù)是用于使用特定的切割符(regex)來分隔字符串成一個字符串數(shù)組,函數(shù)返回是一個數(shù)組。在其中每個出現(xiàn)regex的位置都要進行分解。
需要注意是有以下幾點:
(1)regex是可選項。字符串或正則表達式對象,它標識了分隔字符串時使用的是一個還是多個字符。如果忽略該選項,返回包含整個字符串的單一元素數(shù)組。
(2)limit也是可選項。該值用來限制返回數(shù)組中的元素個數(shù)。
(3)要注意轉(zhuǎn)義字符:“.”和“|”都是轉(zhuǎn)義字符,必須得加"\"。同理:*和+也是如此的。
如果用“.”作為分隔的話,必須是如下寫法:
String.split("\."),這樣才能正確的分隔開,不能用String.split(".");
如果用“|”作為分隔的話,必須是如下寫法:
String.split("\|"),這樣才能正確的分隔開,不能用String.split("|");
(4)如果在一個字符串中有多個分隔符,可以用“|”作為連字符,比如:“acountId=? and act_id =? or extra=?”,把三個都分隔出來,可以用
String.split("and|or");
(5)split函數(shù)結(jié)果與regex密切相關(guān),常見的幾種情況如下所示:
public class SplitTest {
public static void main(String[] args) {
String str1 = "a-b";
String str2 = "a-b-";
String str3 = "-a-b";
String str4 = "-a-b-";
String str5 = "a";
String str6 = "-";
String str7 = "--";
String str8 = "";
split(str1);
split(str2);
split(str3);
split(str4);
split(str5);
split(str6);
split(str7);
split(str8);
}
public static void split(String demo){
String[] array = demo.split("-");
int len = array.length;
System.out.print("\"" + demo + "\" 分割后的長度為:" + len);
if(len >= 0)
{
System.out.print(",分割后的結(jié)果為:");
for(int i=0; i<len; i++)
{
System.out.print(" \""+array[i]+"\"");
}
}
System.out.println();
}
}
運行結(jié)果為:
"a-b" 分割后的長度為:2,分割后的結(jié)果為: "a" "b"
"a-b-" 分割后的長度為:2,分割后的結(jié)果為: "a" "b"
"-a-b" 分割后的長度為:3,分割后的結(jié)果為: "" "a" "b"
"-a-b-" 分割后的長度為:3,分割后的結(jié)果為: "" "a" "b"
"a" 分割后的長度為:1,分割后的結(jié)果為: "a"
"-" 分割后的長度為:0,分割后的結(jié)果為:
"--" 分割后的長度為:0,分割后的結(jié)果為:
"" 分割后的長度為:1,分割后的結(jié)果為: ""
由此可以得出來:
當字符串只包含分隔符時,返回數(shù)組沒有元素;
當字符串不包含分隔符時,返回數(shù)組只包含一個元素(該字符串本身);
字符串最尾部出現(xiàn)的分隔符可以看成不存在,不影響字符串的分隔;
字符串最前端出現(xiàn)的分隔符將分隔出一個空字符串以及剩下的部分的正常分隔;
不知道這么做的原因是什么,所以在使用split()中需要注意這些問題,解決方法其實也挺簡單的,變通下即可。
例如:
String splitString = "\|";
String s = "|42345|||";
s = s+"| ";
String info[] = s.split(splitString);
System.out.println(info.length);
for (int i = 0; i < info.length; i++) {
System.out.println(info[i]+" >>>> " + i);
}
谷歌的guava包,也有對split的重寫,返回的是list數(shù)組集合.
具體使用如下:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>24.1-jre</version>
</dependency>
String line = ",aa,bcd,eef,,,";
List<String> split2 = Splitter.on(",").splitToList(line);
System.out.println(split2.size());//7
根據(jù)結(jié)果,我們可以看到XM代理申請www.fx61.com/brokerlist/xm.html,谷歌的split默認是頭部和尾部的逗號都沒有被忽略,相當于java包下split的limit設(shè)置為-1
相比下,java包下split的limit默認不寫就是0,即頭部逗號沒有被忽略,而尾部逗號是被忽略的
一定要注意區(qū)分
手寫String的split()方法,String的split()方法分三種情況:
regex只有一位,且不為列出的特殊字符;
regex有兩位,第一位位轉(zhuǎn)義字符且第二位不是數(shù)字和字母;
最后一種情況就是正則表達式去拆分字符串。
package com.dalingjia.algorithm.string;
import com.google.common.collect.Lists;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**

創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計制作、成都做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時代的廬江網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

  • 手動實現(xiàn)java的split()方法
    */
    public class SpiltUtil {
    private static final String contant = ".$
    ()[{^?*+\";
    public static String[] splitMethod(String string, String regex){
    char ch = 0;
    int off = 0;
    int next = 0;
    ArrayList<String> list = Lists.newArrayList();
    if(regex.length() == 1 && contant.indexOf(ch = regex.charAt(0)) == -1

    regex.length() ==2 && regex.charAt(0)=='\' && ((ch = regex.charAt(1))-'0'
    '9'-ch)<0 && (ch-'a''z'-ch)<0 && (ch-'A''Z' -ch)<0)
    {
    while ((next = string.indexOf(ch,off)) > 0){
    list.add(string.substring(off, next));
    off = next + 1;
    }
    if(off == 0){
    return new String[]{string};
    }
    list.add(string.substring(off, string.length()));
    return interceptEmpty(list);
    }
    return regexSplit(string, regex);
    }
    private static String[] regexSplit(String string, String regex) {
    int off = 0;
    //將給定的正則表達式編譯到模式中
    Pattern pattern = Pattern.compile(regex);
    //創(chuàng)建給定輸入與此模式匹配的匹配器
    Matcher m = pattern.matcher(string);
    List<String> list = Lists.newArrayList();
    while (m.find()){
    //m.start(): 返回第一個匹配字符的索引
    list.add(string.substring(off, m.start()));
    //m.end(): 返回最后匹配字符之后的偏移量
    off = m.end();
    }
    if(off == 0){
    return new String[]{string};
    }
    list.add(string.substring(off, string.length()));
    return interceptEmpty(list);
    }
    //截取空字符串
    private static String[] interceptEmpty(List<String> list){
    //截取空的字符串
    int resultSize = list.size();
    while (resultSize>0 && list.get(resultSize-1).length() == 0){
    resultSize--;
    }
    String[] strings = new String[resultSize];
    return list.subList(0, resultSize).toArray(strings);}
    //測試方法
    @Test
    br/>}
    //測試方法
    @Test
    //測試regex只有一位,且不為列出的特殊字符
    String s1 = "gg,tge,hbfs,ijkd,,,";
    String[] strings1 = splitMethod(s1, ",");
    for (int i = 0; i < strings1.length; i++) {
    System.out.println(strings1[i]);
    }
    //測試regex有兩位,第一位位轉(zhuǎn)義字符且第二位不是數(shù)字和字母
    String s2 = "bb\'dn\'ags\'kl\'\'";
    String[] strings2 = splitMethod(s2,"\'");
    for (int i = 0; i < strings2.length; i++) {
    System.out.println(strings2[i]);
    }
    //測試正則表達式
    String ss = "ac32dge533grhr139ljs343";
    String[] strings = splitMethod(ss,"[\d]+");
    for (int i = 0; i < strings.length; i++) {
    System.out.println(strings[i]);
    }
    }
    }
    String的split()方法源碼如下:
    public String[] split(String regex, int limit) {
    char ch = 0;
    if (
    ( //如果regex只有一位,且不為列出的特殊字符
    (regex.length() == 1 && ".$
    ()[{^?*+\".indexOf(ch = regex.charAt(0)) == -1)
                //如果regex有2位,第一位為轉(zhuǎn)義字符,且第二位不是數(shù)字或字母
                /**
                 * “||”:   如果左邊計算后的操作數(shù)為true,右邊則不再執(zhí)行,返回true;
                 *
                 * “|”:前后兩個操作數(shù)都會進行計算。也就是說:“|”不存在短路。
                 */
                (regex.length() == 2 && regex.charAt(0) == '\\' && ( ((ch = regex.charAt(1))-'0')|('9'-ch) ) < 0 && ((ch-'a')|('z'-ch)) < 0 && ((ch-'A')|('Z'-ch)) < 0)
            )
                    &&
            /**
             *  UTF-16 編碼中的 Unicode 高代理項代碼單元的最小值, '\uD800'
             *  UTF-16 編碼中的 Unicode 低代理項代碼單元的最大值, '\uDFFF'
             */
            (ch < Character.MIN_HIGH_SURROGATE || ch > Character.MAX_LOW_SURROGATE)
        ){
        int off = 0;
        int next = 0;
        boolean limited = limit > 0;
        ArrayList<String> list = new ArrayList<>();
        while ((next = indexOf(ch, off)) != -1) {
            if (!limited || list.size() < limit - 1) {
                list.add(substring(off, next));
                off = next + 1;
            } else {    // last one
                //assert (list.size() == limit - 1);
                list.add(substring(off, value.length));
                off = value.length;
                break;
            }
        }
        // 如果沒有匹配的,直接返回該字符串
        if (off == 0)
            return new String[]{this};
        // 添加最后一個子序列
        if (!limited || list.size() < limit)
            list.add(substring(off, value.length));
        //截取后面的空字符串
        int resultSize = list.size();
        if (limit == 0) {
            while (resultSize > 0 && list.get(resultSize - 1).length() == 0) {
                resultSize--;
            }
        }
        String[] result = new String[resultSize];
        return list.subList(0, resultSize).toArray(result);
    }
    //第三種情況,利用正則表達式去split字符串
    return Pattern.compile(regex).split(this, limit);

    }
    String的split()方法最后一行調(diào)用的Pattern的split()方法,二則源碼大同小異。
    源碼如下:
    public String[] split(CharSequence input, int limit) {
    int index = 0;
    boolean matchLimited = limit > 0;
    ArrayList<String> matchList = new ArrayList<>();
    Matcher m = matcher(input);
    while(m.find()) {
    if (!matchLimited || matchList.size() < limit - 1) {
    if (index == 0 && index == m.start() && m.start() == m.end()) {
    continue;
    }
    String match = input.subSequence(index, m.start()).toString();
    matchList.add(match);
    index = m.end();
    } else if (matchList.size() == limit - 1) { // last one
    String match = input.subSequence(index, input.length()).toString();
    matchList.add(match);
    index = m.end();
    }
    }
    // 如果沒有匹配的,直接返回該字符串
    if (index == 0)
    return new String[] {input.toString()};
    // 添加最后一個子序列
    if (!matchLimited || matchList.size() < limit)
    matchList.add(input.subSequence(index, input.length()).toString());
    // 截取后面的空字符
    int resultSize = matchList.size();
    if (limit == 0)
    while (resultSize > 0 && matchList.get(resultSize-1).equals(""))
    resultSize--;
    String[] result = new String[resultSize];
    //集合截取
    return matchList.subList(0, resultSize).toArray(result);
    }
    正則表達式的常用方法:
    Pattern.compile(String regex): 將給定的正則表達式編譯到模式中;
    Pattern.split(CharSequence input):按照此模式拆分給定的輸入序列;
    Pattern.matcher(CharSequence input): 創(chuàng)建給定輸入與此模式匹配的匹配器;
    Matcher.find(): 查找與該模式匹配的輸入序列的下一個子序列;
    Matcher.start(): 返回第一個匹配字符的索引;
    Matcher.end(): 返回最后匹配字符之后的偏移量。
    注意:若split后字符串數(shù)組的尾部字符串為"",則需要舍棄空字符串

當前名稱:String的split方法的使用
標題來源:http://bm7419.com/article30/jjshpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標簽優(yōu)化、云服務(wù)器、小程序開發(fā)、企業(yè)網(wǎng)站制作網(wǎng)站設(shè)計公司、網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)