之前没接触过StringTokenizer,看上去类名很长,仿佛很牛13似的。最近了解了一下
StringTokenizer 类允许应用程序将字符串分解为标记
也就是分解字符串用的
让我们来看一个简单的例子
- StringTokenizer st = new StringTokenizer( "this is a test" );
- while (st.hasMoreTokens()) {
- System.out.println(st.nextToken());
- }
StringTokenizer st = new StringTokenizer("this is a test");
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
出去结果如下
- this
- is
- a
- test
this
is
a
test
这种不带参数的StringTokenizer使用的分隔符是/t/n/r/f,即空白字符、制表符、换行符、回车符和换页符。
ok,StringTokenizer还提供了另一种构造方法,StringTokenizer(String str, String delim)
从名字上看,可以知道,我们可以自定义delimiter。那么,这个delimiter是不是可以为正则表达式呢?满怀期待的试验一下
- String input = "This is just a test" ;
- //设想的delimiter可以为正则表达式
- StringTokenizer st = new StringTokenizer(input, "//s{1}" );
- while (st.hasMoreTokens()){
- System.out.println(st.nextToken());
- }
String input = "This is just a test";
//设想的delimiter可以为正则表达式
StringTokenizer st = new StringTokenizer(input,"//s{1}");
while(st.hasMoreTokens()){
System.out.println(st.nextToken());
}
本以为结果会是
- this
- is
- a
- test
this
is
a
test
哪知一看,结果为
- Thi
- i
- ju
- t a te
- t
Thi
i
ju
t a te
t
可见,StringTokenizer的delimeter不可以为正则表达式
替代方法?
首先,来看String的split方法
- String input = "This is just a test" ;
- String [] str = input.split("//s{1}" );
- for ( int i= 0 ;i<str.length;i++){
- System.out.println(str[i]);
- }
String input = "This is just a test";
String [] str = input.split("//s{1}");
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
输出结果为
- this
- is
- a
- test
this
is
a
test
ok,正确。String的split方法接受的参数可以为正则表达式。
我们可以看一下split方法的定义
- public String[] split(String regex) {
- return split(regex, 0 );
- }
public String[] split(String regex) {
return split(regex, 0);
}
其实这个参数他们就是按正则表达式来对待的。(哎,我一直以为只能是字符呢 )
接着来看Scanner的表现。
一个可以使用正则表达式来解析基本类型和字符串的简单文本扫描器
- Scanner scanner = new Scanner(input);
- scanner.useDelimiter("//s{1}" );
- while (scanner.hasNext()){
- ystem.out.println(scanner.next());
- }
Scanner scanner = new Scanner(input);
scanner.useDelimiter("//s{1}");
while(scanner.hasNext()){
System.out.println(scanner.next());
}
同样的,通过设置Delimiter(可以为正则表达式),我们可以很轻松的拆分字符串
输出结果为
- This
- is
- just
- a
- test
This
is
just
a
test
另外,还可以使用Pattern类的split方法,我觉得这个和String的split方法差不多。(Pattern类主要不是用在拆分字符串,而是在正则表达式的应用那里)
- Pattern pattern = Pattern.compile( "//s{1}" );
- str = pattern.split(input);
- for ( int i= 0 ;i<str.length;i++){
- ystem.out.println(str[i]);
- }
Pattern pattern = Pattern.compile("//s{1}");
str = pattern.split(input);
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
结果同样为
- This
- is
- just
- a
- test
This
is
just
a
test
好了,现在已经知道的就有三种方式来代替StringTokenizer了,并且由于StringTokenizer只能做一些很简单的拆分,远不能适应现在的要求,所以,StringTokenizer,你可以放心的撤退了,远离历史舞台吧。
其实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就不要再用了。
//
没有考察过性能。
有时间了,我测试一下。然后补充。
不过不知道不需要正则的切分用处多不多。
很多的是,比如我过去干过的用StringTokenizer来切分memcached文本协议,就比用Pattern.split快多了。
我简单的测试了下。的确是它最快。
不知道我的测试结果科学不科学,请指教
- public static void main(String [] args){
- long start = System.currentTimeMillis();
- for ( int i= 0 ;i< 100000 ;i++){
- test1();
- }
- long end = System.currentTimeMillis();
- System.out.println("StringTokenzier: " +(end-start));
- start = System.currentTimeMillis();
- for ( int i= 0 ;i< 100000 ;i++){
- test2();
- }
- end = System.currentTimeMillis();
- System.out.println("Scanner: " +(end-start));
- start = System.currentTimeMillis();
- for ( int i= 0 ;i< 100000 ;i++){
- test3();
- }
- end = System.currentTimeMillis();
- System.out.println("String: " +(end-start));
- start = System.currentTimeMillis();
- for ( int i= 0 ;i< 100000 ;i++){
- test4();
- }
- end = System.currentTimeMillis();
- System.out.println("Pattern: " +(end-start));
- }
- //用StringTokenizer
- public static void test1(){
- String input = "This is 1 just a test" ;
- StringTokenizer st = new StringTokenizer(input);
- while (st.hasMoreTokens()){
- String s = st.nextToken();
- }
- }
- //用Scanner的方法
- public static void test2(){
- String input = "This is 1 just a test" ;
- Scanner scanner = new Scanner(input);
- scanner.useDelimiter(" " );
- while (scanner.hasNext()){
- String s = scanner.next();
- }
- }
- //用String的split方法
- public static void test3(){
- String input = "This is 1 just a test" ;
- String [] str = input.split(" " );
- for ( int i= 0 ;i<str.length;i++){
- String s = str[i];
- }
- }
- //用Pattern的方法
- public static void test4(){
- Pattern pattern = Pattern.compile(" " );
- String input = "This is 1 just a test" ;
- String [] str = pattern.split(input);
- for ( int i= 0 ;i<str.length;i++){
- String s = str[i];
- }
- }
public static void main(String [] args){
long start = System.currentTimeMillis();
for(int i=0;i<100000;i++){
test1();
}
long end = System.currentTimeMillis();
System.out.println("StringTokenzier: "+(end-start));
start = System.currentTimeMillis();
for(int i=0;i<100000;i++){
test2();
}
end = System.currentTimeMillis();
System.out.println("Scanner: "+(end-start));
start = System.currentTimeMillis();
for(int i=0;i<100000;i++){
test3();
}
end = System.currentTimeMillis();
System.out.println("String: "+(end-start));
start = System.currentTimeMillis();
for(int i=0;i<100000;i++){
test4();
}
end = System.currentTimeMillis();
System.out.println("Pattern: "+(end-start));
}
//用StringTokenizer
public static void test1(){
String input = "This is 1 just a test";
StringTokenizer st = new StringTokenizer(input);
while(st.hasMoreTokens()){
String s = st.nextToken();
}
}
//用Scanner的方法
public static void test2(){
String input = "This is 1 just a test";
Scanner scanner = new Scanner(input);
scanner.useDelimiter(" ");
while(scanner.hasNext()){
String s = scanner.next();
}
}
//用String的split方法
public static void test3(){
String input = "This is 1 just a test";
String [] str = input.split(" ");
for(int i=0;i<str.length;i++){
String s = str[i];
}
}
//用Pattern的方法
public static void test4(){
Pattern pattern = Pattern.compile(" ");
String input = "This is 1 just a test";
String [] str = pattern.split(input);
for(int i=0;i<str.length;i++){
String s = str[i];
}
}
运行了五次。输出结果如下:
- StringTokenzier: 110
- Scanner: 3281
- String: 453
- Pattern: 438
- StringTokenzier: 109
- Scanner: 3297
- String: 453
- Pattern: 438
- StringTokenzier: 110
- Scanner: 3265
- String: 485
- Pattern: 437
- StringTokenzier: 109
- Scanner: 3266
- String: 469
- Pattern: 437
- StringTokenzier: 109
- Scanner: 3297
- String: 469
- Pattern: 422
StringTokenzier: 110
Scanner: 3281
String: 453
Pattern: 438
StringTokenzier: 109
Scanner: 3297
String: 453
Pattern: 438
StringTokenzier: 110
Scanner: 3265
String: 485
Pattern: 437
StringTokenzier: 109
Scanner: 3266
String: 469
Pattern: 437
StringTokenzier: 109
Scanner: 3297
String: 469
Pattern: 422
StringTokenizer最快
Scanner最慢。
String和Pattern速度差不多。Pattern稍快些。
循环外面。
只用一个Pattern
然后当成参数传进去。这就是dennis_zane大哥说的缓存吧。
- public static void test4(Pattern pattern){
- String input = "This is 1 just a test" ;
- String [] str = pattern.split(input);
- for ( int i= 0 ;i<str.length;i++){
- String s = str[i];
- }
- }
- public static void main(String [] args){
- Pattern pattern = Pattern.compile("//s{1}" );
- start = System.currentTimeMillis();
- for ( int i= 0 ;i< 100000 ;i++){
- test4(pattern);
- }
- end = System.currentTimeMillis();
- System.out.println("Pattern: " +(end-start));
- }
public static void test4(Pattern pattern){
String input = "This is 1 just a test";
String [] str = pattern.split(input);
for(int i=0;i<str.length;i++){
String s = str[i];
}
}
public static void main(String [] args){
Pattern pattern = Pattern.compile("//s{1}");
start = System.currentTimeMillis();
for(int i=0;i<100000;i++){
test4(pattern);
}
end = System.currentTimeMillis();
System.out.println("Pattern: "+(end-start));
}
明白?
刚试了下,确实是这样的。
不知道为什么。有空了看下源代码