之前没接触过StringTokenizer,看上去类名很长,仿佛很牛13似的。最近了解了一下


引用



  StringTokenizer 类允许应用程序将字符串分解为标记 



也就是分解字符串用的 
让我们来看一个简单的例子


Java代码 



1. StringTokenizer st = new StringTokenizer("this is a test");  
2. while (st.hasMoreTokens()) {  
3.     System.out.println(st.nextToken());  
4. }


出去结果如下


Java代码 


1. this   
2. is  
3. a  
4. test



这种不带参数的StringTokenizer使用的分隔符是/t/n/r/f,即空白字符、制表符、换行符、回车符和换页符。 
ok,StringTokenizer还提供了另一种构造方法,StringTokenizer(String str, String delim) 
从名字上看,可以知道,我们可以自定义delimiter。那么,这个delimiter是不是可以为正则表达式呢?满怀期待的试验一下


Java代码 



1. String input = "This is just a test";  
2. //设想的delimiter可以为正则表达式  
3. StringTokenizer st = new StringTokenizer(input,"//s{1}");  
4. while(st.hasMoreTokens()){  
5.   System.out.println(st.nextToken());  
6. }



本以为结果会是


Java代码 



1. this  
2. is  
3. a  
4. test


哪知一看,结果为


Java代码 

1.   Thi  
2.  i  
3.  ju  
4. t a te  
5. t



可见,StringTokenizer的delimeter不可以为正则表达式

 

替代方法? 

首先,来看String的split方法

Java代码 

1. String input = "This is just a test";  
2. String [] str = input.split("//s{1}");  
3. for(int i=0;i<str.length;i++){  
4.   System.out.println(str[i]);  
5. }


输出结果为


Java代码 

1. this  
2. is  
3. a  
4. test



ok,正确。String的split方法接受的参数可以为正则表达式。 
我们可以看一下split方法的定义




1. public String[] split(String regex) {  
2. return split(regex, 0);  
3. }



其实这个参数他们就是按正则表达式来对待的。(哎,我一直以为只能是字符呢

 ) 


接着来看Scanner的表现。

引用



一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器 


 


1. Scanner scanner = new Scanner(input);  
2. scanner.useDelimiter("//s{1}");  
3. while(scanner.hasNext()){  
4. ystem.out.println(scanner.next());  
5. }


同样的,通过设置Delimiter(可以为正则表达式),我们可以很轻松的拆分字符串 
输出结果为


Java代码 

1.   This  
2. is  
3. just  
4. a  
5. test


另外,还可以使用Pattern类的split方法,我觉得这个和String的split方法差不多。(Pattern类主要不是用在拆分字符串,而是在正则表达式的应用那里)


1. Pattern pattern = Pattern.compile("//s{1}");  
2. str = pattern.split(input);  
3. for(int i=0;i<str.length;i++){  
4. ystem.out.println(str[i]);  
5. }


结果同样为


Java代码 

1.   This  
2. is  
3. just  
4. a  
5. test



好了,现在已经知道的就有三种方式来代替StringTokenizer了,并且由于StringTokenizer只能做一些很简单的拆分,远不能适应现在的要求,所以,StringTokenizer,你可以放心的撤退了,远离历史舞台吧。 
其实sun也知道这个


sun 写道


<tt>StringTokenizer</tt> is a legacy class that is retained for   
 * compatibility reasons although its use is discouraged in new code. It is   
 * recommended that anyone seeking this functionality use the <tt>split</tt>   
 * method of <tt>String</tt> or the java.util.regex package instead.


ps:那个老帖子是04年的。也许那会还没有这么多的替代方法。 
不过5年过去了。StringTokenizer就不要再用了。

 

 

 

 

 

 

//
 

  dennis_zane 写道 

 

   kaka2008 写道 
 
  

    dennis_zane 写道


不知道你有没有考察过性能。。如果不需要正则,并且切分非常频繁的话,StringTokenizer快上很多。



没有考察过性能。 

有时间了,我测试一下。然后补充。 

不过不知道不需要正则的切分用处多不多。


很多的是,比如我过去干过的用StringTokenizer来切分memcached文本协议,就比用Pattern.split快多了。 




我简单的测试了下。的确是它最快。 
不知道我的测试结果科学不科学,请指教

 

 

 

 

 

 

 


Java代码 


1.         public   static   void  main(String [] args){  
2. long  start = System.currentTimeMillis();  
3. for ( int  i= 0 ;i< 100000 ;i++){  
4.         test1();  
5.     }  
6. long  end = System.currentTimeMillis();  
7. "StringTokenzier: " +(end-start));  
8.       
9.     start = System.currentTimeMillis();  
10. for ( int  i= 0 ;i< 100000 ;i++){  
11.         test2();  
12.     }  
13.     end = System.currentTimeMillis();  
14. "Scanner: " +(end-start));  
15.       
16.     start = System.currentTimeMillis();  
17. for ( int  i= 0 ;i< 100000 ;i++){  
18.         test3();  
19.     }  
20.     end = System.currentTimeMillis();  
21. "String: " +(end-start));  
22.       
23.     start = System.currentTimeMillis();  
24. for ( int  i= 0 ;i< 100000 ;i++){  
25.         test4();  
26.     }  
27.     end = System.currentTimeMillis();  
28. "Pattern: " +(end-start));  
29. }  
30. //用StringTokenizer   
31. public   static   void  test1(){  
32. "This is 1 just a test" ;  
33. new  StringTokenizer(input);  
34. while (st.hasMoreTokens()){  
35.         String s = st.nextToken();  
36.     }  
37. }  
38. //用Scanner的方法   
39. public   static   void  test2(){  
40. "This is 1 just a test" ;  
41. new  Scanner(input);  
42. " " );  
43. while (scanner.hasNext()){  
44.         String s = scanner.next();  
45.     }  
46. }  
47. //用String的split方法   
48. public   static   void  test3(){  
49. "This is 1 just a test" ;  
50. " " );  
51. for ( int  i= 0 ;i<str.length;i++){  
52.         String s = str[i];  
53.     }  
54. }  
55. //用Pattern的方法   
56. public   static   void  test4(){  
57. " " );  
58. "This is 1 just a test" ;  
59.     String [] str = pattern.split(input);  
60. for ( int  i= 0 ;i<str.length;i++){  
61.         String s = str[i];  
62.     }  
63. }



运行了五次。输出结果如下:


Java代码 

1.  StringTokenzier:  110   
2. Scanner: 3281   
3. String: 453   
4. Pattern: 438   
5.   
6. StringTokenzier: 109   
7. Scanner: 3297   
8. String: 453   
9. Pattern: 438   
10.   
11. StringTokenzier: 110   
12. Scanner: 3265   
13. String: 485   
14. Pattern: 437   
15.   
16. StringTokenzier: 109   
17. Scanner: 3266   
18. String: 469   
19. Pattern: 437   
20.   
21. StringTokenzier: 109   
22. Scanner: 3297   
23. String: 469   
24. Pattern: 422



StringTokenizer最快 
Scanner最慢。 
String和Pattern速度差不多。Pattern稍快些。

 


zhouxiang_fly 写道


额,弱弱的问一下,将Pattern改在外面是如何改的。。。



循环外面。 
只用一个Pattern 
然后当成参数传进去。这就是dennis_zane大哥说的缓存吧。


    1. public static void test4(Pattern pattern){    
    2. "This is 1 just a test";    
    3.     String [] str = pattern.split(input);    
    4. for(int i=0;i<str.length;i++){    
    5.         String s = str[i];    
    6.     }    
    7. }  
    8. public static void main(String [] args){   
    9. "//s{1}");  
    10.     start = System.currentTimeMillis();    
    11. for(int i=0;i<100000;i++){    
    12.         test4(pattern);    
    13.     }    
    14.     end = System.currentTimeMillis();    
    15. "Pattern: "+(end-start));   
    16. }



    明白?


    humaeks 写道


    我没记错的话ST遇到"|" 作为字段分隔符会死。



    刚试了下,确实是这样的。 
    不知道为什么。有空了看下源代码