Java 扫描程序与StringTokenizer与String.Split
我刚刚了解了Java的Scanner类,现在我想知道它如何与StringTokenizer和String.Split进行比较/竞争。我知道StringTokenizer和String.Split只对字符串起作用,那么我为什么要对字符串使用扫描仪呢?扫描器仅仅是用来进行拆分的一站式购物吗?它们本质上是课程的马匹Java 扫描程序与StringTokenizer与String.Split,java,java.util.scanner,tokenize,split,Java,Java.util.scanner,Tokenize,Split,我刚刚了解了Java的Scanner类,现在我想知道它如何与StringTokenizer和String.Split进行比较/竞争。我知道StringTokenizer和String.Split只对字符串起作用,那么我为什么要对字符串使用扫描仪呢?扫描器仅仅是用来进行拆分的一站式购物吗?它们本质上是课程的马匹 Scanner专为需要解析字符串、提取不同类型数据的情况而设计。它非常灵活,但可以说它没有提供最简单的API来简单地获取由特定表达式分隔的字符串数组 String.split()和Pat
专为需要解析字符串、提取不同类型数据的情况而设计。它非常灵活,但可以说它没有提供最简单的API来简单地获取由特定表达式分隔的字符串数组Scanner
和String.split()
为您提供了执行后一种操作的简单语法,但它们基本上就是这么做的。如果您想要解析结果字符串,或者根据特定的标记中途更改分隔符,那么它们将不会帮助您Pattern.split()
比StringTokenizer
更具限制性,使用起来也有点烦躁。它本质上是为提取由固定子字符串分隔的令牌而设计的。由于这个限制,它的速度大约是String.split()的两倍。(请参见my。)它也早于正则表达式API,其中String.split()
是其中的一部分String.split()
您将从我的计时中注意到,在典型的机器上,
String.split()
仍然可以在几毫秒内标记数千个字符串。此外,与StringTokenizer
相比,它的优势在于它将输出作为字符串数组,这通常是您想要的。使用StringTokenizer
提供的枚举
,在大多数情况下过于“语法繁琐”。从这个角度来看,StringTokenizer
现在有点浪费空间,您最好只使用String.split()
如果您有一个字符串对象要标记,那么最好使用String的方法而不是StringTokenizer。如果您正在解析来自程序外部源的文本数据,例如来自文件或用户的文本数据,那么扫描仪就会派上用场。StringTokenizer总是在那里。它是最快的,但是枚举式的习语看起来可能没有其他习语那么优雅
split是在JDK1.4上出现的。比标记器慢,但更易于使用,因为它可以从String类调用
扫描仪出现在JDK1.5上。它是最灵活的,填补了Java API上的一个长期空白,可以支持与著名的Cs scanf函数系列相当的功能。让我们从消除这些功能开始。它越来越旧,甚至不支持正则表达式。其文件规定:
StringTokenizer
是一个遗留类,出于兼容性原因保留它,尽管在新代码中不鼓励使用它。建议寻求此功能的任何人改用String
的split
方法或java.util.regex
包
所以让我们马上把它扔掉。那就剩下了。他们之间有什么区别
首先,split()
for (String token : input.split("\\s+") { ... }
扫描仪
更像一条流:
while (myScanner.hasNext()) {
String token = myScanner.next();
...
}
或
(它有一个相当大的范围,所以不要认为它总是局限于这么简单的事情。)
当您在开始解析之前没有(或无法获得)所有输入时,此流样式接口可用于解析简单文本文件或控制台输入
就我个人而言,我能记得的唯一一次使用Scanner
是在学校项目中,当时我必须从命令行获取用户输入。这样做很容易。但是,如果我有一个字符串
,我想拆分它,那么使用split()
字符串几乎不需要动脑筋。split似乎比StringTokenizer慢得多。split的唯一优点是您可以获得一个令牌数组。也可以在split中使用任何正则表达式。
org.apache.commons.lang.StringUtils有一个拆分方法,它比两个viz中的任何一个都快得多。StringTokenizer或String.split。
但这三种处理器的CPU利用率几乎相同。因此,我们还需要一种CPU密集度较低的方法,我仍然无法找到这种方法 最近,我做了一些关于String.split()在性能高度敏感的情况下性能不佳的实验。你可能会发现这很有用
要点是String.split()每次编译一个正则表达式模式,因此与使用预编译的模式对象直接对字符串进行操作相比,它可以降低程序的速度。split速度较慢,但不如Scanner慢。StringTokenizer比split更快。然而,我发现,通过交换一些灵活性,我可以获得双倍的速度,以获得速度提升,这是我在JFastParser做的
在包含一百万个双精度的字符串上进行测试:
Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms
String.split()工作得很好,但有自己的边界,比如如果您想根据单管或双管(|)符号拆分如下所示的字符串,则它不起作用。在这种情况下,可以使用StringTokenizer
ABC | IJK对于默认场景,我也建议使用Pattern.split(),但如果您需要最大的性能(特别是在Android上,我测试的所有解决方案都非常慢),并且您只需要按单个字符分割,我现在使用我自己的方法:
public static ArrayList<String> splitBySingleChar(final char[] s,
final char splitChar) {
final ArrayList<String> result = new ArrayList<String>();
final int length = s.length;
int offset = 0;
int count = 0;
for (int i = 0; i < length; i++) {
if (s[i] == splitChar) {
if (count > 0) {
result.add(new String(s, offset, count));
}
offset = i + 1;
count = 0;
} else {
count++;
}
}
if (count > 0) {
result.add(new String(s, offset, count));
}
return result;
}
public static ArrayList splitBySingleChar(final char[]s,
最终字符拆分(字符){
最终ArrayList结果=新建ArrayList();
最终整数长度=s.length;
整数偏移=0;
整数计数=0;
for(int i=0;i0){
添加(新字符串(s、偏移量、计数));
}
抵消
public static ArrayList<String> splitBySingleChar(final char[] s,
final char splitChar) {
final ArrayList<String> result = new ArrayList<String>();
final int length = s.length;
int offset = 0;
int count = 0;
for (int i = 0; i < length; i++) {
if (s[i] == splitChar) {
if (count > 0) {
result.add(new String(s, offset, count));
}
offset = i + 1;
count = 0;
} else {
count++;
}
}
if (count > 0) {
result.add(new String(s, offset, count));
}
return result;
}
String s = " a bb ccc dddd eeeee ffffff ggggggg ";
ArrayList<String> result = splitBySingleChar(s.toCharArray(), ' ');
String str = "ab cd ef";
StringTokenizer st = new StringTokenizer(str, " ");
for (int i = 0; st.hasMoreTokens(); i++) System.out.println("#" + i + ": " + st.nextToken());
String[] split = str.split(" ");
for (int i = 0; i < split.length; i++) System.out.println("#" + i + ": " + split[i]);
Scanner sc = new Scanner(str).useDelimiter(" ");
for (int i = 0; sc.hasNext(); i++) System.out.println("#" + i + ": " + sc.next());
//StringTokenizer
#0: ab
#1: cd
#2: ef
//String.split()
#0: ab
#1: cd
#2:
#3: ef
//Scanner
#0: ab
#1: cd
#2:
#3: ef