I just learned about Java\'s Scanner class and now I\'m wondering how it compares/competes with the StringTokenizer and String.Split. I know that the StringTokenizer and Str
String.split seems to be much slower than StringTokenizer. The only advantage with split is that you get an array of the tokens. Also you can use any regular expressions in split. org.apache.commons.lang.StringUtils has a split method which works much more faster than any of two viz. StringTokenizer or String.split. But the CPU utilization for all the three is nearly the same. So we also need a method which is less CPU intensive, which I am still not able to find.
They're essentially horses for courses.
Scanner
is designed for cases where you need to parse a string, pulling out data of different types. It's very flexible, but arguably doesn't give you the simplest API for simply getting an array of strings delimited by a particular expression.String.split()
and Pattern.split()
give you an easy syntax for doing the latter, but that's essentially all that they do. If you want to parse the resulting strings, or change the delimiter halfway through depending on a particular token, they won't help you with that.StringTokenizer
is even more restrictive than String.split()
, and also a bit fiddlier to use. It is essentially designed for pulling out tokens delimited by fixed substrings. Because of this restriction, it's about twice as fast as String.split()
. (See my comparison of String.split() and StringTokenizer.) It also predates the regular expressions API, of which String.split()
is a part.You'll note from my timings that String.split()
can still tokenize thousands of strings in a few milliseconds on a typical machine. In addition, it has the advantage over StringTokenizer
that it gives you the output as a string array, which is usually what you want. Using an Enumeration
, as provided by StringTokenizer
, is too "syntactically fussy" most of the time. From this point of view, StringTokenizer
is a bit of a waste of space nowadays, and you may as well just use String.split()
.
One important difference is that both String.split() and Scanner can produce empty strings but StringTokenizer never does it.
For example:
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());
Output:
//StringTokenizer
#0: ab
#1: cd
#2: ef
//String.split()
#0: ab
#1: cd
#2:
#3: ef
//Scanner
#0: ab
#1: cd
#2:
#3: ef
This is because the delimiter for String.split() and Scanner.useDelimiter() is not just a string, but a regular expression. We can replace the delimiter " " with " +" in the example above to make them behave like StringTokenizer.
Let's start by eliminating StringTokenizer. It is getting old and doesn't even support regular expressions. Its documentation states:
StringTokenizer
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 thesplit
method ofString
or thejava.util.regex
package instead.
So let's throw it out right away. That leaves split() and Scanner. What's the difference between them?
For one thing, split()
simply returns an array, which makes it easy to use a foreach loop:
for (String token : input.split("\\s+") { ... }
Scanner
is built more like a stream:
while (myScanner.hasNext()) {
String token = myScanner.next();
...
}
or
while (myScanner.hasNextDouble()) {
double token = myScanner.nextDouble();
...
}
(It has a rather large API, so don't think that it's always restricted to such simple things.)
This stream-style interface can be useful for parsing simple text files or console input, when you don't have (or can't get) all the input before starting to parse.
Personally, the only time I can remember using Scanner
is for school projects, when I had to get user input from the command line. It makes that sort of operation easy. But if I have a String
that I want to split up, it's almost a no-brainer to go with split()
.