1

次のリンクを見てください。

http://snippetsofjosh.wordpress.com/tag/advantages-and-disadvantages-of-arraylist/

これが、(Array)List ではなく Array を常に使用することを好む理由の 1 つです。それでも、メモリ管理と速度について考えさせられました。

したがって、次の質問にたどり着きました。

ファイルのサイズ (/エントリ数) がわからない場合に、ファイルからデータを保存する最良の方法は何ですか(最良とは「計算時間の最小量」として定義されます) 。

以下に、3 つの異なる方法を紹介します。どの方法が最適で、その理由を知りたいと思います。質問を明確にするために、配列で終わる必要があると仮定しましょう。また、.txt ファイルのすべての行に 1 つのエントリ (/1 つの文字列) しかないと仮定しましょう。また、質問の範囲を限定するために、この質問は Java のみに限定します。

というファイルから次の情報を取得するとしますwords.txt

Hello
I 
am
a
test 
file

方法 1 - 二重で危険

File read = new File("words.txt");
Scanner in = new Scanner(read);

int counter = 0;

while (in.hasNextLine())
{
    in.nextLine();
    counter++;
}

String[] data = new String[counter];

in = new Scanner(read);

int i = 0;

while (in.hasNextLine())
{
    data[i] = in.nextLine();
    i++;
}

方法 2 - 明確だが冗長

File read = new File("words.txt");
Scanner in = new Scanner(read);

ArrayList<String> temporary = new ArrayList<String>();

while (in.hasNextLine())
{
    temporary.add(in.nextLine());
}

String[] data = new String[temporary.size()];

for (int i = 0; i < temporary.size(); i++)
{
    data[i] = temporary.get(i);
}

方法 3 - 短いが堅い

File read = new File("words.txt");
FileReader reader = new FileReader(read);

String content = null;

char[] chars = new char[(int) read.length()];
reader.read(chars);
content = new String(chars);

String[] data = content.split(System.getProperty("line.separator"));

reader.close(); 

別の方法 (さらに良い方法) がある場合は、以下に入力してください。また、必要に応じてコードを自由に調整してください。


答え:

配列にデータを格納する最速の方法は、次の方法です。

File read = new File("words.txt");
Scanner in = new Scanner(read);

ArrayList<String> temporary = new ArrayList<String>();

while (in.hasNextLine()) {
    temporary.add(in.nextLine());
}

String[] data = temporary.toArray(new String[temporary.size()]);

Java 7 以降の場合:

Path loc = Paths.get(URI.create("file:///Users/joe/FileTest.txt"));
List<String> lines = Files.readAllLines(loc, Charset.defaultCharset());
String[] array = lines.toArray(new String[lines.size()]);
4

5 に答える 5

3

すべてのソースコードとの非常に良い比較がここにありますjava_tip_how_read_files_quickly

概要:

最高の Java 読み取りパフォーマンスを得るには、次の 4 つの点に注意してください。

  • 一度に 1 バイトではなく配列を読み取ることで、I/O 操作を最小限に抑えます。8K バイトの配列が適切なサイズです。
  • データを一度に 1 バイトではなく、一度に配列として取得することにより、メソッド呼び出しを最小限に抑えます。配列のインデックスを使用して、配列内のバイトを取得します。
  • スレッド セーフが必要ない場合は、スレッド同期ロックを最小限に抑えます。スレッドセーフなクラスへのメソッド呼び出しを減らすか、FileChannel や MappedByteBuffer などの非スレッドセーフなクラスを使用してください。
  • JVM/OS、内部バッファ、およびアプリケーション アレイ間のデータ コピーを最小限に抑えます。FileChannel をメモリ マッピングで使用するか、直接またはラップされた配列 ByteBuffer を使用します。

それが役立つことを願っています。

編集

私はそのようにします:

File read = new File("words.txt");
Scanner in = new Scanner(read);    
List<String> temporary = new LinkedList<String>();

while (in.hasNextLine()) {
    temporary.add(in.nextLine());
}

String[] data = temporary.toArray(new String[temporary.size()]);

主な違いは、(他の 2 つの方法とは対照的に) データを 1 回だけ読み取ることと、リンクリストへの追加が非常に安価であることです+ 行に対する余分な操作 (分割など) は必要ありません - ここでは arraylist を使用しないでください

于 2013-06-26T12:21:44.870 に答える
3

ここでは、best とはより速いことを意味すると思います。

方法 2 を使用しますが、 Collection インターフェイスによって提供されるメソッドを使用して配列を作成します。

String[] array = temporary.toArray(new String[temporary.size()]);

またはさらに単純です(Java 7+):

List<String> lines = Files.readAllLines(file, charset);
String[] array = lines.toArray(new String[lines.size()]);

その他の方法:

  • 方法 1 は 2 つのパスを実行するため、ファイルの読み取りが配列リストのサイズ変更よりも効率的である可能性はほとんどありません。
  • 方法3が速いかどうかはわかりません

アップデート:

完全を期すために、上記のように変更し、すべてのバイトを一度に読み取り、文字列を作成して新しい行に分割する追加のメソッド ( ) を含むマイクロベンチマークを実行しました。結果 (ミリ秒単位):method2method4

Benchmark   Mean 
method1     126.178
method2     59.679
method3     76.622
method4     75.293

編集:

より大きな 3 MB のファイル ( LesMiserables.txt ) を使用すると、結果は一貫しています。

Benchmark      Mean 
method1     608649.322
method2      34167.101
method3      63410.496
method4      65552.79
于 2013-06-26T12:14:11.773 に答える
2

ファイルからデータを読み取る場合、ボトルネックはファイル読み取り (IO) 段階になります。ほとんどの場合、処理にかかる時間はわずかです。ですから、正しく安全なことをしてください。まず、正しくします。それからあなたはそれを速くします。

ファイルのサイズがわからない場合は、ある種の動的に拡張するデータ構造が必要です。それは何ですかArrayList。自分で書いたコードが、Java API の重要な部分よりも効率的または正確である可能性は低いです。したがって、ArrayListオプション 2 を使用してください。

于 2013-06-26T12:15:59.157 に答える
1
List<String> lines = Files.readAllLines(yourFile, charset);
String[] arr = lines.toArray(new String[lines.size()]);
于 2013-06-26T12:25:37.053 に答える
1

私はグァバを使います

File file = new File("words.txt");
List<String> lines = Files.readLines(file, Charset.defaultCharset());
// If it really has to be an array:
String[] array = lines.toArray(new String[0]);
于 2013-06-26T12:18:09.367 に答える