`
kaka2008
  • 浏览: 91824 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

StringTokenizer,洗洗睡吧

    博客分类:
  • java
阅读更多
前几天看一个老帖子
http://www.iteye.com/topic/7279?page=2
其中凤舞凰扬前辈说到了StringTokenizer。
之前没接触过StringTokenizer,看上去类名很长,仿佛很牛13似的。最近了解了一下
引用

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

也就是分解字符串用的
让我们来看一个简单的例子
     StringTokenizer st = new StringTokenizer("this is a test");
     while (st.hasMoreTokens()) {
         System.out.println(st.nextToken());
     }

出去结果如下
     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());
   }

本以为结果会是
     this
     is
     a
     test

哪知一看,结果为
  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]);
  }

输出结果为
     this
     is
     a
     test

ok,正确。String的split方法接受的参数可以为正则表达式。
我们可以看一下split方法的定义
  public String[] split(String regex) {
        return split(regex, 0);
  }

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

接着来看Scanner的表现。
引用

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

  Scanner scanner = new Scanner(input);
  scanner.useDelimiter("\\s{1}");
  while(scanner.hasNext()){
	System.out.println(scanner.next());
  }

同样的,通过设置Delimiter(可以为正则表达式),我们可以很轻松的拆分字符串
输出结果为
  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++){
	System.out.println(str[i]);
  }

结果同样为
  This
is
just
a
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就不要再用了。
StringTokenizer,洗洗睡吧。
分享到:
评论
18 楼 logicgate 2009-09-19  
支持火星人,支持基础贴,给个良好!
17 楼 zhouxiang_fly 2009-09-18  
kaka2008 写道
zhouxiang_fly 写道
额,弱弱的问一下,将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)); 
}

明白?
humaeks 写道
我没记错的话ST遇到"|" 作为字段分隔符会死。

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

treblesoftware 写道
哈哈,洗洗睡还太早,这东西好象还有些用。

讨论技术,就严谨点。
有没有用,写点例子,具体来说说啊。



看来我还是没理解错啊,我试了下,感觉速度也没怎么快啊。。。好像还有慢的趋势。。
16 楼 mrushui 2009-09-18  
split是可以使用"|"的,写作split("\\|")就行了。
15 楼 whaosoft 2009-09-18  
为什么sun都不鼓励用了~~
14 楼 fuliang 2009-09-18  
不支持正则风格,肯定要比使用了正则的要快了,如果你只是简单的分割,使用StringTokenizer还是很好的。从其他语言也可以见到类似的并存问题,如php的explode和
preg_split。
13 楼 kaka2008 2009-09-18  
zhouxiang_fly 写道
额,弱弱的问一下,将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)); 
}

明白?
humaeks 写道
我没记错的话ST遇到"|" 作为字段分隔符会死。

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

treblesoftware 写道
哈哈,洗洗睡还太早,这东西好象还有些用。

讨论技术,就严谨点。
有没有用,写点例子,具体来说说啊。
12 楼 treblesoftware 2009-09-18  
哈哈,洗洗睡还太早,这东西好象还有些用。
11 楼 humaeks 2009-09-18  
我没记错的话ST遇到"|" 作为字段分隔符会死。
10 楼 zhouxiang_fly 2009-09-18  
额,弱弱的问一下,将Pattern改在外面是如何改的。。。
9 楼 kaka2008 2009-09-18  
dennis_zane 写道
Pattern可以缓存的,编译一次后重复使用,而不要每次都重新compile。String.split很方便,但是如果调用频繁,还是会造成性能影响,因此在频繁调用的地方,更推荐直接用Pattern.split,并且缓存Pattern.

哦,改了一下。
将Pattern改在了外面,比上面能快了些。
但和StringTokenizer比还是3点几倍

有一点不明白。既然有这个差距了,sun为什么不鼓励我们使用它了呢?难道sun没有测试这个的性能
8 楼 dennis_zane 2009-09-18  
Pattern可以缓存的,编译一次后重复使用,而不要每次都重新compile。String.split很方便,但是如果调用频繁,还是会造成性能影响,因此在频繁调用的地方,更推荐直接用Pattern.split,并且缓存Pattern.
7 楼 kaka2008 2009-09-18  
        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

StringTokenizer最快
Scanner最慢。
String和Pattern速度差不多。Pattern稍快些。
6 楼 kaka2008 2009-09-18  
dennis_zane 写道
kaka2008 写道
dennis_zane 写道
不知道你有没有考察过性能。。如果不需要正则,并且切分非常频繁的话,StringTokenizer快上很多。


没有考察过性能。
有时间了,我测试一下。然后补充。
不过不知道不需要正则的切分用处多不多。


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


我简单的测试了下。的确是它最快。
不知道我的测试结果科学不科学,请指教
5 楼 dennis_zane 2009-09-18  
kaka2008 写道
dennis_zane 写道
不知道你有没有考察过性能。。如果不需要正则,并且切分非常频繁的话,StringTokenizer快上很多。


没有考察过性能。
有时间了,我测试一下。然后补充。
不过不知道不需要正则的切分用处多不多。


很多的是,比如我过去干过的用StringTokenizer来切分memcached文本协议,就比用Pattern.split快多了。
4 楼 kaka2008 2009-09-18  
dennis_zane 写道
不知道你有没有考察过性能。。如果不需要正则,并且切分非常频繁的话,StringTokenizer快上很多。


没有考察过性能。
有时间了,我测试一下。然后补充。
不过不知道不需要正则的切分用处多不多。
3 楼 dennis_zane 2009-09-18  
不知道你有没有考察过性能。。如果不需要正则,并且切分非常频繁的话,StringTokenizer快上很多。
2 楼 kaka2008 2009-09-18  
snowolf 写道
目前很多书还是要求使用这个类,甚至包括经典教材,呵呵!

也许是那些经典教材出版时间比较早。
连sun都不鼓励我们用了,呵呵
1 楼 snowolf 2009-09-18  
目前很多书还是要求使用这个类,甚至包括经典教材,呵呵!

相关推荐

Global site tag (gtag.js) - Google Analytics