Как читать целые числа из файла, когда производительность является проблемой?

Я делаю некоторые задачи на CodeEval. По сути, задача очень проста: "Распечатать сумму всех целых чисел, прочитанных из файла".

Мое решение следующее:

import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;

public class SumIntegersFromFile {

    public static void main(String args[]) throws IOException{

        File file = new File(args[0]);
         BufferedReader br = new BufferedReader( new FileReader(file));
         String line;
         int i=0;
         while((line=br.readLine())!=null){
            int k = Integer.parseInt(line);
             i+=k;
         }
         br.close();
         System.out.println(i);
    }
}

Но мне сказали, что это решение не является оптимальным с точки зрения производительности.

Код основан на рекомендациях в вопросе Лучший способ прочитать текстовый файл. Единственное отличие здесь - я читаю целые числа вместо строк.

Какой самый эффективный способ чтения целых чисел из файла в Java?

2 ответа

Решение

Если вам явно не сказано иное, вы не должны предполагать, что общая сумма будет соответствовать int, Попробуйте изменить тип i к longили даже BigIntegerи посмотреть, если это имеет значение для вашего счета.

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

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

(И, вероятно, вам сказали, что это одна запись в строке...)

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

Я не вижу ничего плохого в производительности вашего кода. То есть я оспариваю утверждение, что с вашей программой что-то не так.

Чтение данных из файлов или по сети происходит на несколько порядков медленнее, чем манипулирование данными в памяти. Поэтому производительность кода, который смешивает ввод-вывод с некоторыми манипуляциями с данными в памяти, обычно определяется временем, затрачиваемым на ввод-вывод. Твики к манипулированию данными в памяти редко стоят того. Если операции ввода / вывода происходят параллельно с манипулированием данными (что будет иметь место, если O/S выполняет некоторое чтение с опережением), манипулирование данными может быть практически бесплатным: ускорение манипулирования данными не приведет к сокращению времени, затрачиваемого на выполнение, потому что уменьшение времени процессора для манипулирования данными будет точно компенсировано увеличением времени, которое программа блокирует в ожидании ввода.

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

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

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

Другие вопросы по тегам