Получение ввода в разных строках с помощью токенизатора строк

Я использовал Scanner(System.in) в течение долгого времени, но теперь я перехожу на использование BufferedReader и StringTokenizer, потому что я слышал, что он работает быстрее. Я пытаюсь прочитать ввод (показан ниже), используя StringTokenizer. Я просмотрел некоторые сообщения, но не вижу ни одного, который решает эту конкретную проблему.

5
2 3 2 2 3

Это мой код:

import java.util.*;
import java.io.*;
public class FindDistinct {

    public static void main(String[] args) throws IOException {
        
        BufferedReader r = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter pw = new PrintWriter(System.out);
        StringTokenizer st = new StringTokenizer(r.readLine());
        int n = Integer.parseInt(st.nextToken());
        HashSet<Integer> set = new HashSet<Integer>();
        
        for (int i = 0; i < n; i++) {
            set.add(Integer.parseInt(st.nextToken()));
        }
        
        pw.println(set.size());
        pw.close();
        r.close();
        
    }

}

Ошибка, которую я получаю:

Exception in thread "main" java.util.NoSuchElementException
    at java.base/java.util.StringTokenizer.nextToken(StringTokenizer.java:348)
    at FindDistinct.main(FindDistinct.java:16)

Я думаю, что ошибка возникает из-за того, что я читаю несколько строк ввода. Как это исправить? Кстати, это для соревновательного программирования, поэтому я ищу решения, которые будут работать быстро. Заранее спасибо!


person Tee Swizzle    schedule 20.12.2020    source источник


Ответы (1)


Из Javadoc для StringTokenizer:

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

Но ваша проблема в том, что вы читаете только одну строку из своего буферизованного считывателя, поэтому ваш токенизатор имеет только один токен, но затем вы пытаетесь прочитать из него следующие n токена.

Вам нужно прочитать еще одну строку и создать еще один StringTokenizer.

Я сомневаюсь, что какая-либо разница в производительности между этим подходом и Scanner будет важна. В вопросах соревновательного программирования ключевым моментом является поиск эффективного алгоритма.

person tgdavies    schedule 20.12.2020