Более быстрая реализация более чем одного ввода в одной строке (Java) - PullRequest
3 голосов
/ 26 марта 2012

Ну, это может быть глупой проблемой.

Мне просто нужна более быстрая реализация следующей задачи

Я хочу взять три целочисленных ввода в одной строке, например:

10 34 54

Один из способов - создать BufferedReader, а затем использовать readLine (), который будет читать всю строку как строку, а затем мы можем использовать StringTokenizer для разделения трех целых чисел.(Медленная реализация)

Другим способом является использование «Сканера» и получение ввода методом nextInt ().(Медленнее, чем в предыдущем методе)

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

Моя реализация:

BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

for(i=0;i<n;i++) {
    str=br.readLine();
    st = new StringTokenizer(str);
    t1=Integer.parseInt(st.nextElement().toString());
    t2=Integer.parseInt(st.nextElement().toString());
    z=Long.parseLong(st.nextElement().toString());
}

Эта петля повторяется n раз.(n - количество записей) Поскольку я знаю, что каждая строка будет содержать только три целых числа, нет необходимости проверять hasMoreElements()

Ответы [ 3 ]

3 голосов
/ 26 марта 2012

Я просто хочу быстрее реализовать следующую задачу.

Скорее всего, вам НЕ НУЖНА быстрая реализация. Шутки в сторону. Даже с входным файлом в 2 миллиона строк.

Скорее всего, что:

  • больше времени уходит на обработку файла, чем на его чтение, и
  • Большая часть «времени чтения» тратится на выполнение действий на уровне операционной системы или просто на ожидание чтения следующего блока диска.

Мой совет: не стоит оптимизировать этот , если приложение в целом не займет слишком много времени для запуска. И когда вы обнаружите, что это так, профилируйте приложение и используйте статистику профиля, чтобы сообщить вам, куда стоит потратить усилия на оптимизацию.

(Мое интуитивное чувство заключается в том, что оптимизация этой части вашего приложения не принесет многого. Но не полагайтесь на это. Профилируйте его!)

0 голосов
/ 26 марта 2012

Вот что я имею в виду, когда говорю «специализированный сканер».В зависимости от эффективности синтаксического анализатора (или разбиения), это может быть немного быстрее (вероятно, это не так):

BufferedReader br=new BufferedReader(...);  
for(i=0;i<n;i++) 
{     
    String str=br.readLine();
    long[] resultLongs = {-1,-1,-1};
    int startPos=0;
    int nextLongIndex=0;
    for (int p=0;p<str.length();p++)
    {
        if (str.charAt(p)== ' ')
        {
            String intAsStr=str.substring(startPos, p-1);
            resultLongs[nextLongIndex++]=Integer.parseInt(intAsStr);
            startpos=p+1;
        }
    }
    // t1, t2 and z are in resultLongs[0] through resultLongs[2]     
    }

Hths.

И, конечно, это не помогает, если входной файл содержитмусор, т. е. все, кроме длинных, разделенных пробелами.

И, кроме того, чтобы свести к минимуму «обходы» ОС, неплохо бы снабдить буферизованный ридер нестандартным (больше стандартного)) буфер.

Уточнен другой совет, который я дал в комментарии: если вам нужно читать такой огромный текстовый файл более одного раза, то есть более одного раза после его обновления, вы можете прочитать все длинные вструктура данных (может быть список элементов, содержащих три длинных), и поток в файл «кеш».В следующий раз сравните метку времени текстового файла с файлом «кэша».Если он старше, прочитайте файл кеша.Поскольку потоковый ввод / вывод не сериализует long в свое строковое представление, вы увидите намного лучшее время чтения.

EDIT: пропущено переназначение startPos.РЕДАКТИРОВАТЬ 2: Добавлено объяснение идеи кеша.

0 голосов
/ 26 марта 2012

Вот простой пример, который будет довольно быстрым:

public static void main(String[] args) throws IOException {
    BufferedReader reader = new BufferedReader(new FileReader("myfile.txt"));
    String line;
    while ((line = reader.readLine()) != null) {
        for (String s : line.split(" ")) {
            final int i = Integer.parseInt(s);
            // do something with i...
        }
    }
    reader.close();
}

Однако ваша задача в основном займет время.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...