关于split函数

在java.lang包中也有String.split()方法,与.net的类似,都是返回是一个字符型数组,但使用过程中还有一些小技巧。如执行:

1 String str = "1|23|4|56|7";
2  String[] arr = str.split("|");
3  for (int i = 0; i < arr.length; i++) {
4      System.out.println(arr[i]);
5  }

出来的结果是:

 1  
 2  1
 3  |
 4  2
 5  3
 6  |
 7  4
 8  |
 9  5
10  6
11  |
12  7

奇怪吧,不过注意看一下API说明还是知道原因的。

所以正常的写法是这样的:

  1. 如果用“.”作为分隔的话,必须是如下写法:String.split("\\."),这样才能正确的分隔开,不能用String.split(".");
  2. 如果用“|”作为分隔的话,必须是如下写法:String.split("\\|"),这样才能正确的分隔开,不能用String.split("|");
  3. “.”和“|”都是转义字符,必须得加"\\";
  4. 如果在一个字符串中有多个分隔符,可以用“|”作为连字符,比如:“a=1 and b =2 or c=3”,把三个都分隔出来,可以用String.split("and|or")。


1.正则表达式字符串问题

首先输入的regex是一个正则表达式,而不是一个普通的字符串,所以导致很多在正则表达式里面有特殊意义的比如 "." "|" "\" ,如果直接使用是不行的,另外一个方面我们输入的regex是以字符串形式传递的,对有些字符必须要转义,尤其是"\",下面请看例子

String[] aa = "aaa|bbb|ccc".split("|");//wrong
String[] aa = "aaa|bbb|ccc".split("\\|"); //

 

 String[] aa = "aaa*bbb*ccc".split("*");//wrong
 String[] aa = "aaa|bbb|ccc".split("\\*");

 

 String[] aa = "aaa*bbb*ccc".split(".");//wrong
 String[] aa = "aaa|bbb|ccc".split("\\.");

 

String[] aa = "aaa\\bbb\\bccc".split("\\");//wrong

String[] aa = "aaa\\bbb\\bccc".split("\\\\");

 

2.数组长度的问题

String a = "";
String[] b = a.split(",");
b.length为 1;
*
String a = "c";
String[] b = a.split(",");
b.length为 1;
**
String a = "c,,,";
String[] b = a.split(",");
b.length为 1;
***
String a = "c,,c";
String[] b = a.split(",");
b.length为 3;
****
String a = ",";
String[] b = a.split(",");
b.length为 0;

 

其实只要添加一个参数即可,例如

String str = "abcdef,ghijk,lmno,pqrst,,,";       

String[] array = str.split(",");
输出:abcdef,ghijk,lmno,pqrst,

 

String str = "abcdef,ghijk,lmno,pqrst,,,";
String[] array 
= str.split(",",-1);

输出:abcdef,ghijk,lmno,pqrst,,,,

 

public String [] split (String  regex, int limit) 

最后一个参数limit是影响返回数组的长度的


关于字符创分割姿势

关于字符串的分割,我用jdk的split、apache的common的split、正则表达式、StringTokenizerr以及substring做了以下比较,比较的时间为纳秒,用一个字符串“192.168.20.121”作为示例,

打印时间为:

使用jdk的split切分字符串
192  168  20  121  花费时间1086171
使用common的split切分字符串
192  168  20  121  花费时间9583620
使用StringTokenizer的切分字符串
192  168  20  121  花费时间184380
使用jdk的pattern切分字符串
192  168  20  121  花费时间222654
使用jdk的substring切分字符串
192  168  20  121  花费时间157562
虽然每次打印的时间不太相同,但是基本相差不大。


通过以上分析得知使用substring和StringTokenizer的效率相对较高,其它相对较差。

为什么StringTokenizer的性能相对好些呢?通过分析发现

StringTokener.hasMoreElement和String.split(String.split是用正则表达式匹配,所以不使用KMP字符串匹配算法)用的都是按顺序遍历的算法,时间复杂度O(m*n),较高。

不过StringTokener是一边按顺序遍历,一边返回每个分组;而Spring.split是全部分组完成,再返回字符串数组。这个区别不大,但是如果我们不需要全部都分组,只需要某个分组的字符串,那么StringTokener性能会好点。

apacheJakatar的StringUtils一样用了KMP算法(按序查找字符串,时间是O(m+n)),按理说效率应该最高,但是为啥性能会比较差呢,需要进一步研究。不过有一个优点是如果使用一些转义字符
如“.”、“|”等不需要加"\\",如果使用jdk的split必须加转义。

附源码:

    String ip ="192.168.20.121";

  
  long st1 = System.nanoTime();
  String[] ips =ip.split("\\.");
  System.out.println("使用jdk的split切分字符串");
  for (int i = 0; i < ips.length; i++) {
   System.out.print(ips[i]+"  ");
  }
  System.out.println("花费时间"+(System.nanoTime()-st1));
  long st2 = System.nanoTime();
  ips= StringUtils.split(ip,"\\.");
  System.out.println("使用common的split切分字符串");
  for (int i = 0; i < ips.length; i++) {
   System.out.print(ips[i]+"  ");
  }
  System.out.println("花费时间"+(System.nanoTime()-st2));
  
  long st3 = System.nanoTime();
  System.out.println("使用StringTokenizer的切分字符串");
  StringTokenizer token=new StringTokenizer(ip,".");
  while(token.hasMoreElements()){
   System.out.print(token.nextToken()+"  ");
  }
  System.out.println("花费时间"+(System.nanoTime()-st3));
  
  long st4 = System.nanoTime();
  Pattern pattern = Pattern.compile("\\.");
  ips =pattern.split(ip);
  System.out.println("使用jdk的pattern切分字符串");
  for (int i = 0; i < ips.length; i++) {
   System.out.print(ips[i]+"  ");
  }
  System.out.println("花费时间"+(System.nanoTime()-st4));
  
  long st5 = System.nanoTime();
  System.out.println("使用jdk的indexOf切分字符串");
  int k=0,count=0;
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < ip.length(); i++) {
   if(ip.substring(i, i+1).equals(".")){
    if(count==0){
     System.out.print(ip.substring(0, i)+"  ");
    }else if(count==1){
     System.out.print(ip.substring(k+1, i)+"  ");
    }else{
     System.out.print(ip.substring(k+1, i)+"  ");
     System.out.print(ip.substring(i+1, ip.length())+"  ");
    }
    k=i;count++;
   }
  }
  System.out.println("花费时间"+(System.nanoTime()-st5));
  
 }



字符串分割有三种方法,如下:

1.用split()方法进行分割,分割开的子字符串放入数组,然后进行处理。
示例代码如下:

public class SplitTest {

public static void main(String[] args) {
String str="I love Dannie";//定义字符串
String[] array= new String[10];
array=str.split(" ");
for(String a :array){
System.out.println(a+" ");
}
}
}


2.用StringTokenizer类进行操作《姿势注意》
示例代码如下:

import java.util.StringTokenizer;
public class StringTokenizerTest {

public static void main(String[] args) {
String str = new String("I love dannie,and i miss her");//定义一个 字符串
StringTokenizer token = new StringTokenizer(str, " ,");//按照空格和逗号进行截取
String[] array = new String[10];//定义一个字符串数组
int i = 0;
while (token.hasMoreTokens()) {
array[i] = token.nextToken();//将分割开的子字符串放入数组中
i++;
}
for (int j = 0; j < array.length; j++) {
System.out.print(array[j] + "  ");//遍历输出数组
}
}
}


3.用indexOf()方法进行定位,然后用substring()进行截取,然后操作。
示例代码如下:

public class FengeString {

public static void main(String[] args) {
String str = "I love dannie";
String[] array = new String[10];//定义数组
String temp = str;//定义一个 字符串变量,把str赋给他,保持str字符串不变

for (int i = 0; i < array.length; i++) {
int index = temp.indexOf(" ");//寻找空格的位置
System.out.println("index=" + index);
if (index == -1) {
array[i] = temp;//找不到空格的时候表示就剩下最后一个字符串了 ,不需要分割,直接赋值给数组,然后break跳出循环。
break;
}
array[i] = temp.substring(0, index);
temp = temp.substring(index + 1);
System.out.println("temp=" + temp);
}
System.out.println("---------------------------");

for (String a : array) {
System.out.print(a + " ");
}
System.out.println();
System.out.println("---------------------------");

for (int i = 0; i < array.length; i++) {
if (("").equals(array[i]) || null == array[i]) {
break;
}
System.out.print(array[i] + " ");
}
}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值