1

私は巨大な行列を生成するプログラムを持っていて、それが計算されたら、後でそれを再利用する必要があります。そのため、後で読み取ることができるように、ローカルハードディスクにキャッシュしたいと思います。私は単にデータをファイルに書き込んでから後でそれを読み取ることによってそれを使用しています。

しかし、Javaでそのようなタスクを実行するために考慮すべき特別なことはありますか。たとえば、シリアル化する必要がありますか、それとも何か特別なことをする必要がありますか。重要なアプリケーションの使用状況データを保存するようなことをするために注意しなければならないことがありますか。プレーンASCII/xmlである必要がありますか、それとも何ですか?
データは機密ではありませんが、データの整合性は重要です。

4

5 に答える 5

2

データを保存するためのいくつかのオプションがあります。ヘッダーに幅を記述し、区切り文字(、、、など)を使用してすべてをリストに入れるだけで試すことができ'\n'ます。それ以外の場合は、特別なObjectOutputStreamを使用してデータを保存できます。注意してください。これは、ソリューションよりも非効率的である可能性があります。ただし、使いやすくなります。'\t'' '

それ以外は、自由に選択できます。私は通常FileWriterを使用し、すべてのデータをプレーンテキストで書き込みます。超効率を求めるなら、FileOutputStreamが必要です。

于 2011-06-26T16:46:45.210 に答える
2

データが非常に大きい場合は、バイナリ形式をお勧めします。これにより、読み取り、特に解析が小さくなり、高速になります(XMLまたはJSONは、バイナリデータの読み取り/書き込みよりも何倍も遅くなります)。シリアル化も多くのオーバーヘッドをもたらすため、DataInputStreamとDataOutputStreamを確認することをお勧めします。特定のタイプの数字のみを書き込むことがわかっている場合、またはデータがどのような順序になるかがわかっている場合は、これらが確かに最速のものです。

ファイルストリームをバッファストリームでラップすることを忘れないでください。バッファストリームを使用すると、操作がさらに高速になります。

次のようなものです(8192はバッファサイズの例です-ニーズに合わせて調整できます):

    final File file = null; // get file somehow
    final DataOutputStream dos = new DataOutputStream(
       new BufferedOutputStream(new FileOutputStream(file), 8192));
    try {
        for (int x: ....) { //loop through your matrix (might be different if matrix is sparse)
           for (int y: ....) {
               if (matrix[x,y] != 0.0) {
                   dos.writeInt(x);
                   dos.writeInt(y);
                   dos.writeDouble(matrix[x,y]);                                     
               } 
           }
        }
     } finally {
       dos.writeInt(-1); // mark end (might be done differently)
       dos.close();
     }

および入力:

    final File file = null; // get file somehow
    final DataInputStream dis = new DataInputStream(
      new BufferedInputStream(new FileInputStream(file), 8192));
    try {
        int x;
        while((x = dis.readInt()) != -1) { 
           int y = dis.readInt();
           double value = dis.readDouble();
           // store x,y, value in matrix
        } 
    } finally {
       dis.close();
    }

Ryan Amosが正しく指摘しているように、行列がスパースでない場合は、値を書き込むだけの方が高速である可能性があります(ただし、すべての値)。

外:

    dos.write(xSize);
    dos.write(ySize);
    for (int x=0; x<xSize; x++) {
        for (int y=0; y<ySize; y++) {
            value = matrix[x,y];
            dos.write(value);
        }
    }

の:

   int xSize = dis.readInt();
   int ySize = dis.readInt();
   for (int x=0; x<xSize; x++) {
        for (int y=0; y<ySize; y++) {
              double value = dis.readDouble();
              matrix[x,y] = value;
        }
   }

(私はそれをコンパイルしていないことに注意してください-それであなたはいくつかのものを修正する必要があるかもしれません-それは私の頭のてっぺんから外れています)。

バッファがないと、バイトごとに読み取るため、速度が低下します。

もう1つのコメント-このような巨大なデータセットでは、SparseMatrixの使用を検討し、ゼロ以外の要素のみを書き込み/読み取りする必要があります(重要な要素が実際に多数ある場合を除く)。

上記のコメントに書かれているように、そのサイズのマトリックス内のすべての要素を本当に書き込み/読み取りたい場合は、すでに数秒ではなく数時間の書き込みについて話していることになります。

于 2011-06-26T16:50:00.780 に答える
1

エントリが数値の場合は、行列の各行を、区切り文字で区切られた1行としてファイルに保存できます。その場合、特別なシリアル化は必要ありません。:)

于 2011-06-26T16:44:46.500 に答える
1

それはすべて、後でどのように出力するか、またはデータベースやその他の場所に保存するかどうかによって異なります。出力したり、他の場所に保存したりしない場合は、テキストファイルが機能します。

于 2011-06-26T16:47:27.367 に答える
1

データを永続化する必要がない場合(つまり、Javaプログラムの終了後にデータを保持する必要がない場合)、Java変数のメモリ内に保持する方が高速です。要件を満たす必要のあるタイプはたくさんあります(ハッシュマップ、配列リスト...)。後続のプログラム実行で使用するためにデータを保持する必要がある場合は、標準のファイル読み取り/書き込みメソッドを使用してファイルに保存できます。プレーンASCIIは、XMLよりも読み取り/書き込みが高速です。ファイルの整合性に関しては、OSに関連しています。これは、最終的にはローカルファイルシステム上のファイルになるためです。

于 2011-06-26T16:48:59.083 に答える