2

LinkedHashMap に文字列のリストであるファイルを読み込む Java で書かれたプログラムがあります。次に、2 つの列で構成される 2 番目のファイルを取得し、各行について、右側の用語が HashMap の用語の 1 つと一致するかどうかを確認します。問題は、実行速度が非常に遅いことです。

コード スニペットを次に示します。これは、2 番目のファイルを HashMap 用語と比較する場所です。

String output = "";

infile = new File("2columns.txt");
        try {
            in = new BufferedReader(new FileReader(infile));
        } catch (FileNotFoundException e2) {
            System.out.println("2columns.txt" + " not found");
        }

        try {
            fw = new FileWriter("newfile.txt");

            out = new PrintWriter(fw);

            try {
                String str = in.readLine();

                while (str != null) {
                    StringTokenizer strtok = new StringTokenizer(str);

                    strtok.nextToken();
                    String strDest = strtok.nextToken();

                    System.out.println("Term = " + strDest);

                    //if (uniqList.contains(strDest)) {
                    if (uniqMap.get(strDest) != null) {
                        output += str + "\r\n";
                        System.out.println("Matched! Added: " + str);
                    }

                    str = in.readLine();
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            out.print(output);

最初に ArrayList から LinkedHashMap に切り替えることでパフォーマンスが向上しましたが、まだ時間がかかります。これをスピードアップするにはどうすればよいですか?

4

2 に答える 2

4

主なボトルネックは、while ループの反復ごとに StringTokenizer を再作成していることです。これをループの外に移動すると、かなり役立つ場合があります。文字列定義を while ループの外側に移動すると、わずかなスピードアップが得られます。

最大の高速化は、おそらくStreamTokenizerを使用することから得られます。例については、以下を参照してください。

ああ、@Doug Ayersが上記のコメントで言っているように、LinkedHashMapの代わりにHashMapを使用してください:)

そして、コードのプロファイリングに関する @ MДΓΓ БДLL の提案は大成功です。このEclipseプロファイリングの例をチェックしてください

    Reader r = new BufferedReader(new FileReader(infile));
StreamTokenizer strtok = new StreamTokenizer(r);
String strDest ="";
while (strtok.nextToken() != StreamTokenizer.TT_EOF) {
    strDest=strtok.sval; //strtok.toString() might be safer, but slower
    strtok.nextToken();

    System.out.println("Term = " + strtok.sval);

    //if (uniqList.contains(strDest)) {
    if (uniqMap.get(strtok.sval) != null) {
        output += str + "\r\n";
        System.out.println("Matched! Added: " + strDest +" "+ strtok.sval);
    }

    str = in.readLine();
}

最後に、ファイルへの書き込みは、最後に一度に行うと、ファイルへの書き込みも高速になる可能性があるということです (これについては自信がありません)。つまり、すべての一致を何らかのバッファに保存し、1 回のヒットで書き込みを行います。

于 2012-04-19T04:41:23.337 に答える
2

StringTokenizer はレガシー クラスです。推奨される代替方法は、文字列の「分割」方法です。

一部の試行は統合される場合があります。1 回の試行で複数のキャッチを取得できます。

LinkedHashMap の代わりに HashMap を使用するという提案は良いものです。リスト構造を維持する必要がないため、get と put のパフォーマンスがわずかに速くなります。

「出力」文字列は、文字列ではなく StringBuilder である必要があります。それは大いに役立つ可能性があります。

于 2012-04-19T04:53:23.910 に答える