JAVA中字符串的split方法有两个陷阱需要注意


在开发过程中,我们会碰到一种场景,需要对字符串进行分割,从而得到更具体的信息。

比如下面这个字符串:

String str = "123455#JAVA编程思想#这是一本JAVA圣经级别的书籍!";

该字符串包含书籍ID、书籍名称以及简介,三条信息用#号连接在一起。

想要得到这三条信息,我们通常使用split方法:

String[] strArray = str.split("#");
for (int i = 0; i < strArray.length; i++) {
    System.out.println(strArray[0]);// 书籍ID
    System.out.println(strArray[1]);// 书籍名称
    System.out.println(strArray[2]);// 简介
}

split使用很简单,但一不小心,很容易掉进两个陷阱:

split的参数是正则表达式,不是字符串对象

当大家看到str.split("#")时,很容易误解#是一个字符串对象,实际上JDK中 split方法定义的是正则表达式。

所以当要分割的字符串是正则表达式中的特殊符号时,执行split方法就不会得到预期的结果。

比如分隔符由#变为 |

String str = "123455|JAVA编程思想|这是一本JAVA圣经级别的书籍!";

String[] strArray = str.split("|");
for (int i = 0; i < strArray.length; i++) {
    System.out.println(i + " >> " + strArray[i]);
}

执行结果是:

0 >> 1
1 >> 2
2 >> 3
3 >> 4
4 >> 5
5 >> 5
6 >> |
7 >> J
8 >> A
9 >> V
10 >> A
11 >> 编
12 >> 程
13 >> 思
14 >> 想
15 >> |
16 >> 这
17 >> 是
18 >> 一
19 >> 本
20 >> J
21 >> A
22 >> V
23 >> A
24 >> 圣
25 >> 经
26 >> 级
27 >> 别
28 >> 的
29 >> 书
30 >> 籍
31 >> !

要解决这个问题,有两种方法:

1、对特殊字符做转义

正则表达式中转义是\ ,所以split的参数应该是\|,然而\ 在JAVA中也是转义字符,即也是特殊字符,也需要转移,所以最终split的参数是\\|

修改后的代码就是:

String str = "123455|JAVA编程思想|这是一本JAVA圣经级别的书籍!";

String[] strArray = str.split("\\|");
for (int i = 0; i < strArray.length; i++) {
    System.out.println(i + " >> " + strArray[i]);
}

2、将特殊字符放在中括号中

正则表达式中,中括号是用来定义匹配的字符范围。

修改后的代码是:

String str = "123455|JAVA编程思想|这是一本JAVA圣经级别的书籍!";

String[] strArray = str.split("[|]");
for (int i = 0; i < strArray.length; i++) {
    System.out.println(i + " >> " + strArray[i]);
}

使用split方法时,有的特殊字符需要注意,那哪些字符需要特别关注呢?

正则表达式中有11个特殊字符:^$|.*+?(){}\/

除了/之外,直接用其他特殊字符分割字符串,都不会得到预期的结果。

甚至在使用*+?{}作为分割字符串时,编译就报错,强制我们去做转义。

为了保证split分割的结果是正确的,也为了减少记忆特殊字符串的麻烦,我建议大家在使用split时,就将分割字符串放在中括号中。即使用第二种方式:

String[] strArray = str.split("[|]");

split分割后的数组长度可能小于预期的长度

对字符串进行分割后,我们可能会将这些信息赋值给一个对象,比如:

String str = "123455#JAVA编程思想#这是一本JAVA圣经级别的书籍!";

String[] strArray = str.split("[#]");
Book book = new Book();
book.setId(strArray[0]);
book.setName(strArray[1]);
book.setDesc(strArray[2]);

一般情况下这是没有问题的,但是如果分割的字符串最后没有书籍简介,就会出问题:

String str = "123455#JAVA编程思想#";

String[] strArray = str.split("[#]");
for (int i = 0; i < strArray.length; i++) {
    System.out.println(i + " >> " + strArray[i]);
}

执行代码的结果是:

0 >> 123455
1 >> JAVA编程思想

也就是分割后的数组长度是2,而我们预期的长度是3,所以执行book.setDesc(strArray[2])代码就会报错。

如果想让上面的字符串分割后的数组长度为3,应该怎么处理?split方法中提供了第二个参数:

String str = "123455#JAVA编程思想#";

String[] strArray = str.split("[#]", 3);
for (int i = 0; i < strArray.length; i++) {
    System.out.println(i + " >> " + strArray[i]);
}

执行代码的结果是:

0 >> 123455
1 >> JAVA编程思想
2 >>

查看JDK的源码,可以发现split只传一个参数时,实际上第二个参数默认传的是0。

java 提取中括号值 java获取括号中的字符串_字符串


当第二个参数limit的值大于0时,表示将字符串分割为几段(也就是数组长度),但这个长度也不能大于字符串中分割字符串的个数+1。

String str = "a##b#";
String[] arr1 = str.split("[#]", 2);
/**
分割后的数组为:
arr1[0] = "a";
arr1[1] = "#b#";
*/

String[] arr2 = str.split("[#]", 3);
/**
分割后的数组为:
arr2[0] = "a";
arr2[1] = "";
arr2[2] = "b#";
*/

String[] arr3 = str.split("[#]", 4);
/**
分割后的数组为:
arr3[0] = "a";
arr3[1] = "";
arr3[2] = "b";
arr3[3] = "";
*/

String[] arr4 = str.split("[#]", 5);
/**
字符串中的#有3个,最多能分割成长度为4的数组,所以第二个参数传5时,结果和传4是一样的:
arr4[0] = "a";
arr4[1] = "";
arr4[2] = "b";
arr4[3] = "";
*/

当第二个参数limit的值小于0时,结果就有些出人意料了,得到的数组是完全按照指定字符分割的。

String str = "a##b#";
String[] arr1 = str.split("[#]", -1);
/**
分割后的数组为:
arr1[0] = "a";
arr1[1] = "";
arr1[2] = "b";
arr1[3] = "";
*/

总结

1、在使用split对字符串进行分割时,将分隔符放在中括号中。str.split("[|]")

2、当要通过数组游标获取分割后的信息时,split第二个参数传入一个负值。str.split('[|]', -1)

注意到这两点,你在使用split方法时就绝对不会出错啦!

看到这里,你是否应该马上搜索代码,看看split的使用都正确了?如果没有,立即改正吧!