Цикл Java через массив - Оптимизация

У меня есть некоторый код Java, который работает вполне ожидаемым образом, но это занимает некоторое время - несколько секунд, даже если задание просто перебирает массив.

Входной файл представляет собой файл Fasta, как показано на изображении ниже. Файл, который я использую, имеет размер 2,9 МО, и есть несколько других файлов Fasta, которые могут занимать до 20 МО.

введите здесь описание изображения

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

AGC - Ser / CUG Leu / ... и т.д.

Так что не так с кодом? и есть ли способ сделать это лучше? Любая оптимизация? Перебор всей строки занимает некоторое время, может быть, всего несколько секунд, но нужно найти лучший способ сделать это.

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

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

        File fastaFile;
        FileReader fastaReader;
        BufferedReader fastaBuffer = null;
        StringBuilder fastaString = new StringBuilder();

        try {
            fastaFile = new File("res/NC_017108.fna");
            fastaReader = new FileReader(fastaFile);
            fastaBuffer = new BufferedReader(fastaReader);
            String fastaDescription = fastaBuffer.readLine();
            String line = fastaBuffer.readLine();

            while (line != null) {
                fastaString.append(line);
                line = fastaBuffer.readLine();
            }

            System.out.println(fastaDescription);
            System.out.println();
            String currentFastaAcid;

            for (int i = 0; i < fastaString.length(); i+=3) {
                currentFastaAcid = fastaString.toString().substring(i, i + 3);
                System.out.println(currentFastaAcid);
            }

        } catch (NullPointerException e) {
            System.out.println(e.getMessage());
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        } finally {
            fastaBuffer.close();
        }

    }

}

person oudouz    schedule 26.10.2013    source источник
comment
Я не знаю, почему это занимает больше времени, чем ожидалось, единственное, что я могу упомянуть, это то, что StringBuilder имеет встроенную подстроку метода, поэтому вы можете избежать создания строки (toString()) перед удалением подпоследовательности.   -  person felix fritz    schedule 26.10.2013


Ответы (5)


Важным фактором здесь является то, что вы каждый раз выполняете вызов подстроки по новой строке.

Вместо этого используйте подстроку непосредственно над построителем строк.

for (int i = 0; i < fastaString.length(); i+=3){
    currentFastaAcid = fastaString.substring(i, i + 3);
    System.out.println(currentFastaAcid);
}

Кроме того, вместо того, чтобы каждый раз печатать текущий FastaAcid, сохраните его в список и распечатайте этот список в конце.

List<String> acids = new LinkedList<String>();

for (int i = 0; i < fastaString.length(); i+=3){
    currentFastaAcid = fastaString.substring(i, i + 3);
    acids.add(currentFastaAcid);
}

System.out.println(acids.toString());
person Evans    schedule 26.10.2013

currentFastaAcid = fastaString.toString().substring(i, i + 3);

Пожалуйста, замените на

currentFastaAcid = fastaString.substring(i, i + 3);

Метод toString StringBuilder создает новый экземпляр объекта String каждый раз, когда вы его вызываете. Он по-прежнему содержит копию всей вашей большой строки. Если вы вызовете подстроку непосредственно из StringBuilder, она вернет небольшую копию подстроки. Также удалите System.out.println, если он вам не нужен.

person vadimvolk    schedule 26.10.2013

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

currentFastaAcid = fastaString.toString().substring(i, i + 3);

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

person Thorsten Schöning    schedule 26.10.2013

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

person drop.in.ocean    schedule 26.10.2013

Если вы удалите

System.out.println(currentFastaAcid);

строку в цикле for, вы выиграете вполне приличное время.

person kerberos84    schedule 26.10.2013