【发布时间】:2016-12-28 10:03:03
【问题描述】:
我有一个大文本文件 (+100MB),每一行都是一个整数(包含 1000 万个数字)。当然,大小和数量可能会发生变化,所以我事先不知道。
我想将文件加载到int[],以尽可能快地处理。首先我想到了这个解决方案:
public int[] fileToArray(String fileName) throws IOException
{
List<String> list = Files.readAllLines(Paths.get(fileName));
int[] res = new int[list.size()];
int pos = 0;
for (String line: list)
{
res[pos++] = Integer.parseInt(line);
}
return res;
}
速度非常快,5.5 秒。其中,readAllLines 调用耗时 5.1s,循环耗时 0.4s。
但后来我决定尝试使用 BufferedReader,并得出了这个不同的解决方案:
public int[] fileToArray(String fileName) throws IOException
{
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(fileName)));
ArrayList<Integer> ints = new ArrayList<Integer>();
String line;
while ((line = bufferedReader.readLine()) != null)
{
ints.add(Integer.parseInt(line));
}
bufferedReader.close();
int[] res = new int[ints.size()];
int pos = 0;
for (Integer i: ints)
{
res[pos++] = i.intValue();
}
return res;
}
这甚至更快! 3.1 秒,while 循环只需 3 秒,for 循环甚至不到 0.1 秒。
我知道这里没有太多优化空间,至少在时间上是这样,但使用 ArrayList 然后使用 int[] 对我来说似乎内存太多了。
关于如何加快速度或避免使用中间 ArrayList 的任何想法?
为了比较,我用 FreePascal 在 1.9 秒内完成了同样的任务 [见编辑],使用 TStringList 类和 StrToInt 函数。
编辑:由于我使用 Java 方法的时间很短,所以我必须改进 FreePascal 方法。 330~360ms。
【问题讨论】:
-
看起来您已经收集了一些好的指标。你可能想看看stackoverflow.com/questions/13155700/…
-
你可以试试这个 ArrayList
ints = new ArrayList (); Integer[] res = ints.toArray(new Integer[ints.size()]); -
你能通过获取文件大小来估计文件中整数的数量吗?您可以将它作为构造函数中的初始容量传递给 ArrayList,也许它不需要增长这么多次。
-
@WW。我试过了,没有明显区别。
-
你的 FreePascal 是否使用 Unicode(Java 内部确实使用了一种 UTF-16,因此每个 char 占用两个字节;Java 9 将为 latin-1 字符串提供更紧凑的编码)?在 Java 中,
Strings 是一流的对象,这是有一定成本的。 +++ 你的平台编码是什么?使用new InputStreamReader(new FileInputStream(...), encoding)可能会加快速度。
标签: java arrays performance