Java中String类split方法源码及使用分析

本文探讨了Java中String类的split方法在处理分隔符为正则表达式时的问题,解释了为何使用'.'作为分隔符会遇到意料之外的结果。通过分析源码,揭示了split方法的第一个参数需考虑正则元字符的转义,以及第二个参数对分隔次数和结果数组长度的影响。了解这些细节有助于更精确地使用split方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在项目对接时,对方对一个字符串使用小数点.来作为分隔符,使用String的split(".")方法处理出现了问题,阅读了一下String类的源码,发现了问题所在。
先举个列子看一下这个问题

String str = "xxx.yyy.zzz";
String[] strs = str.split(".");
System.out.println(strs.length);

运行结果 : 0;
来看看一下String源码中这个方法的实现

 public String[] split(String regex) {
        return split(regex, 0);
    }

继续看split(regex, 0)这个两个参数的方法,我们先讨论第一个参数,String regex ,在源码中对这个参数是这样描述的

the delimiting regular expression

意思是分隔正则表达式,说明split分隔符是根据正则表达式匹配的,而不是简单的字符匹配,再来看方法的实现

 char ch = 0;

        if (((regex.value.length == 1 &&
             ".$|()[{^?*+\\".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)) &&
            (ch < Character.MIN_HIGH_SURROGATE ||
             ch > Character.MAX_LOW_SURROGATE))

"\\.$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1)"

这个表达式的意思是要判断字符串".$|()[{^?*+\"中是否包含参数regex的第一位字符,方法中是希望不包含的,其实 . $ | ()…等这几个字符是正则表达式的特殊字符,都有确切含义,如果使用他们作为分隔符,是要进行转义的“\\.” “\\$” 以为\也是特殊字符,所以先对\转义,所以有两个\\。来试一下

String str = "xxx.yyy.zzz";
String[] strs = str.split("\\.");
System.out.println(strs.length);

运行结果 : 3
这里整个表达式的意思在源码里有说明如下

fastpath if the regex is a
(1)one-char String and this character is not one of the
RegEx’s meta characters “.$|()[{^?*+\”, or
(2)two-char String and the first char is the backslash and
the second is not the ascii digit or ascii letter.

意思字符长度为一的话那么这个字符不能是正则元字符.$|()[{^?*+\其中之一;
长度为二的话 那么第一个字符是反斜杠且第二个字符不是字母或数字;

试一下

String str = "xxx\\ayyy\\azzz";
System.out.println(str);
String[] strs1 = str.split("\\a");
String[] strs2 = str.split("\\\\a");
System.out.println(strs1.length);
System.out.println(strs2.length);

结果是 :
xxx\ayyy\azzz
1
3
下面来看第二个参数

* <p> The {@code limit} parameter controls the number of times the

     * pattern is applied and therefore affects the length of the resulting

     * array.  If the limit <i>n</i> is greater than zero then the pattern

     * will be applied at most <i>n</i>&nbsp;-&nbsp;1 times, the array's

     * length will be no greater than <i>n</i>, and the array's last entry

     * will contain all input beyond the last matched delimiter.  If <i>n</i>

     * is non-positive then the pattern will be applied as many times as

     * possible and the array can have any length.  If <i>n</i> is zero then

     * the pattern will be applied as many times as possible, the array can

     * have any length, and trailing empty strings will be discarded.


源码中对这个参数的描述如上,意思是:
1.如果limit是一个正数,那么最多分个limit-1次,且分割之后的数组长度不会超过limit,数组的最后一个元素将包含最后一次分隔之后剩下的所有字符;

在这里插入图片描述
2.如果limit小于0,那么就会分隔尽可能多次
在这里插入图片描述

3.如果limit等于0,那么就会分隔尽可能多次,且结尾的空字符串将会被丢弃

在这里插入图片描述
至此,String的split用法已经很清晰了,当只有一个参数是,执行的是split(regex,0),当我们只需要截取恰面一部分上,就可以用到两个参数的split来进行截取;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值