Вопрос-ответ

Scanner vs. StringTokenizer vs. String.Split

Сканер против StringTokenizer против String.Разделить

Я только что узнал о классе Java Scanner, и теперь мне интересно, как он сравнивается / конкурирует с StringTokenizer и String .Разделить. Я знаю, что StringTokenizer и String .Split работает только со строками, так зачем мне использовать Scanner для строки? Scanner предназначен только для универсального использования при разделении?

Переведено автоматически
Ответ 1

По сути, это лошади для курсов.


  • Scanner предназначен для случаев, когда вам нужно проанализировать строку, извлекая данные разных типов. Он очень гибкий, но, возможно, не дает вам простейшего API для простого получения массива строк, разделенных определенным выражением.

  • String.split() и Pattern.split() предоставляют вам простой синтаксис для выполнения последнего, но это, по сути, все, что они делают. Если вы хотите разобрать результирующие строки или изменить разделитель на полпути в зависимости от конкретного токена, они вам в этом не помогут.

  • StringTokenizer еще более строгий, чем String.split(), а также немного более неудобный в использовании. По сути, он предназначен для извлечения токенов, разделенных фиксированными подстроками. Из-за этого ограничения это примерно в два раза быстрее, чем String.split(). (Смотрите мое сравнение String.split() и StringTokenizer.) Он также предшествует API регулярных выражений, частью которого String.split() является.

Из моих таймингов вы заметите, что String.split() все еще можно токенизировать тысячи строк за несколько миллисекунд на обычной машине. Кроме того, у него есть преимущество перед StringTokenizer в том, что он выдает вам выходные данные в виде массива строк, что обычно и является тем, что вам нужно. Использование Enumeration, как предусмотрено StringTokenizer, в большинстве случаев слишком "синтаксически сложное". С этой точки зрения, StringTokenizer в настоящее время это пустая трата места, и вы можете просто использовать String.split().

Ответ 2

Давайте начнем с исключения StringTokenizer. Он устарел и даже не поддерживает регулярные выражения. В его документации говорится:


StringTokenizer это устаревший класс, который сохранен по соображениям совместимости, хотя его использование в новом коде не рекомендуется. Всем, кто ищет эту функциональность, рекомендуется вместо этого использовать split метод String или java.util.regex пакет.


Итак, давайте сразу отбросим это. Остаются split() и Scanner. В чем разница между ними?

Во-первых, split() просто возвращает массив, что упрощает использование цикла foreach:

for (String token : input.split("\\s+") { ... }

Scanner построен больше как поток:

while (myScanner.hasNext()) {
String token = myScanner.next();
...
}

или

while (myScanner.hasNextDouble()) {
double token = myScanner.nextDouble();
...
}

(У него довольно большой API, поэтому не думайте, что он всегда ограничен такими простыми вещами.)

Этот интерфейс в стиле потока может быть полезен для синтаксического анализа простых текстовых файлов или консольного ввода, когда у вас нет (или вы не можете получить) всех входных данных перед началом синтаксического анализа.

Лично я помню единственный раз, когда использовал Scanner, это для школьных проектов, когда мне приходилось получать пользовательский ввод из командной строки. Это упрощает такого рода операции. Но если у меня есть String что я хочу разделить, это почти несложно сделать split().

Ответ 3

StringTokenizer был всегда. Он самый быстрый из всех, но идиома, подобная перечислению, может выглядеть не так элегантно, как другие.

split появился в JDK 1.4. Медленнее, чем tokenizer, но проще в использовании, поскольку его можно вызвать из класса String .

Сканер появился в JDK 1.5. Он является наиболее гибким и заполняет давний пробел в Java API для поддержки эквивалента известного семейства функций Cs scanf.

Ответ 4

Split работает медленно, но не так медленно, как Scanner. StringTokenizer работает быстрее, чем split. Однако я обнаружил, что могу увеличить скорость вдвое, используя некоторую гибкость, что я и сделал в JFastParser https://github.com/hughperkins/jfastparser

Тестирование на строке, содержащей миллион двойных значений:

Scanner: 10642 ms
Split: 715 ms
StringTokenizer: 544ms
JFastParser: 290ms
2023-09-27 15:31 java