0

我有一些 Java 代码可以按预期的方式运行,但它需要一些时间——几秒钟——即使工作只是循环遍历一个数组。

输入文件是一个 Fasta 文件,如下图所示。我使用的文件是 2.9Mo,还有一些其他的 Fasta 文件最多可以占用 20Mo。

在此处输入图像描述

在代码中,我试图通过三组循环遍历它,例如:AGC TTT TCA ... 等 该代码目前没有功能感知,但我想要将每个氨基酸附加到它的等效碱基束。例子 :

AGC - Ser / CUG Leu / ...等

那么代码有什么问题?有什么办法可以做得更好吗?有什么优化吗?遍历整个 String 需要一些时间,可能只需几秒钟,但需要找到更好的方法来做到这一点。

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();
        }

    }

}
4

5 回答 5

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

请替换为

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

StringBuilder 的 toString 方法每次调用它时都会创建 String 对象的新实例。它仍然包含所有大字符串的副本。如果您直接从 StringBuilder 调用子字符串,它将返回子字符串的一个小副本。如果您真的不需要它,也可以删除 System.out.println。

于 2013-10-26T13:57:32.483 回答
1

这里的重要因素是您每次都在新字符串上调用子字符串。

相反,直接在 stringbuilder 上使用 substring

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

此外,不是每次都打印 currentFastaAcid,而是将其保存到列表中并在最后打印此列表

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());
于 2013-10-26T13:43:39.053 回答
1

除了调试输出之外,您的主要问题肯定是,您正在创建一个新字符串,并在循环的每次迭代中从文件中完全读取数据:

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

fastaString.toString() 将在每次迭代中给出相同的结果,因此是多余的。把它放在循环之外,你肯定会节省几秒钟的运行时间。

于 2013-10-26T13:55:07.660 回答
1

除了建议的串行代码优化外,我将进行并行处理以进一步减少时间。如果你有非常大的文件,你可以将读取文件和处理读取行的工作分成不同的线程。这样,当一个线程忙于从大文件中读取下一行时,其他线程可以处理读取行并在控制台上打印它们。

于 2013-10-26T14:05:57.903 回答
0

如果您删除

System.out.println(currentFastaAcid);

在 for 循环中添加一行,您将获得相当不错的时间。

于 2013-10-26T13:41:26.817 回答