我在CodeEval上做了一些任务。基本上任务很简单:“打印出从文件中读取的所有整数的总和”。
我的解决方案如下:
import java.io.File;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
public class SumIntegersFromFile {
public static void main(String args[]) throws IOException{
File file = new File(args[0]);
BufferedReader br = new BufferedReader( new FileReader(file));
String line;
int i=0;
while((line=br.readLine())!=null){
int k = Integer.parseInt(line);
i+=k;
}
br.close();
System.out.println(i);
}
}
但有人告诉我,从性能的角度来看,这个解决方案并不是最优的。
该代码基于问题Best way to read a text file中的建议。这里唯一的区别是我正在读取整数而不是字符串。
从Java文件中读取整数的性能最有效的方法是什么?
答案 0 :(得分:1)
除非您明确告知其他情况,否则您不应该认为总数将适合int
。尝试将i
的类型更改为long
,甚至更改为BigInteger
,并查看这是否会对您的分数产生影响。
您可以尝试对k
(并使用Long.parseLong(line)
)执行相同的操作。这取决于问题的确切措辞,但也许个别值也可能超过int
的限制。
还有一件事......问题,就像你已经说过的那样,只是说你应该把所有的整数加起来。这样就有可能存在不是整数的行,在这种情况下你应该跳过它们,而不是抛出NumberFormatException
(这是你的代码目前会做的)。
(并且大概有人告诉你,每行一个条目......)
但是如果你想要挤出最后一点性能,你需要将文件读作二进制而不是逐行:将每一行转换为String
太贵了。有关如何操作的详细说明,请参阅this question on summing integers from a text file。
答案 1 :(得分:1)
我认为您的代码性能没有任何问题。也就是说,我对你的程序有任何问题的说法提出异议。
从文件或网络中读取数据比在内存中操作数据慢几个数量级。因此,将I / O与内存中的数据操作混合的代码的性能通常由I / O所花费的时间决定。调整内存中数据的操作很少值得。如果I / O操作与数据操作同时发生(如果O / S执行一些预读就会出现这种情况),数据操作几乎是免费的:使数据操作更快不会减少所需的时间数据操作的CPU时间减少将被程序在等待输入时阻塞的时间量的增加精确地抵消。
执行I / O并需要良好性能的程序必须减少等待I / O所花费的时间。它们的运行方式应使其能够利用硬件和操作系统提供的优化来减少阻塞量。
重要的是,在低级别,磁盘和网络不会在每个操作的少量字节上运行。他们使用更大的数据包或块。与操作系统交互以读取比存储在一个磁盘块中更少的字节是浪费的。程序通过缓冲其I / O来避免这样做,因此程序本身会将许多小I / O操作的序列更改为更少但更大的操作。您使用的是BufferedReader
,因此您已经在使用{。}了。
操作系统可能会进行一些预读:如果你在文件开头的块中询问字节,它会猜测你可能会按顺序读取文件,所以它是值得的还要获取文件的一些后续块,以期您的程序也需要这些块。顺序读取文件可提供更好的性能你已经这样做了。