上下文:给定一个目录,我想列出其中包含名称模式的所有文件,按lastModified
时间戳排序,并将此列表格式化为Json字符串,我会得到每个文件的名称和时间戳:
[{"name": "somefile.txt", "timestamp": 123456},
{"name": "otherfile.txt", "timestamp": 456789}]
我有以下代码:
private StringBuilder jsonFileTimestamp(File file) {
return new StringBuilder("{\"name\":\"")
.append(file.getName())
.append("\", \"timestamp\":")
.append(file.lastModified())
.append("}");
}
public String getJsonString(String path, String pattern, int skip, int limit) throws IOException {
return Files.list(Paths.get(path))
.map(Path::toFile)
.filter(file -> {
return file.getName().contains(pattern);
})
.sorted((f1, f2) -> {
return Long.compare(f2.lastModified(), f1.lastModified());
})
.skip(skip)
.limit(limit)
.map(f -> jsonFileTimestamp(f))
.collect(Collectors.joining(",", "[", "]"));
}
这很好用。我只关心StringBuilder实例化(或字符串连接)的性能。只要文件数量很少就可以了(这是我的情况,所以我很好),但我很好奇:你会建议什么作为优化?我觉得我应该使用reduce
和正确的累加器和组合器,但我无法绕过它。
感谢。
我终于接受了以下“优化”:
private StringBuilder jsonFileTimestampRefactored(StringBuilder res, File file) {
return res.append(res.length() == 0 ? "" : ",")
.append("{\"name\":\"")
.append(file.getName())
.append("\", \"timestamp\":")
.append(file.lastModified())
.append("}");
}
public String getJsonStringRefactored(String path, String pattern, int skip, int limit) throws IOException {
StringBuilder sb = Files.list(Paths.get(path))
.map(Path::toFile)
.filter(file -> file.getName().contains(pattern))
.sorted((f1, f2) -> Long.compare(f2.lastModified(), f1.lastModified()))
.skip(skip)
.limit(limit)
.reduce(new StringBuilder(),
(StringBuilder res, File file) -> jsonFileTimestampRefactored(res, file),
(StringBuilder a, StringBuilder b) -> a.append(a.length() == 0 || b.length() == 0 ? "" : ",").append(b))
;
return new StringBuilder("[").append(sb). append("]").toString();
}
这个版本只创建了2个StringBuilder
个实例,而旧版本实例的实例化数量与目录中的文件数量相同。
在我的工作站上,第一个实现需要1289毫秒来完成超过3379个文件,而第二个实现需要1306毫秒。第二个实现是在我预期(非常小)的节省时花费我多1%的时间。
我不觉得新版本更容易阅读或维护,所以我会保留旧版本。
谢谢大家。
答案 0 :(得分:8)
字符串格式化是应用程序性能的一个微不足道的部分,它几乎不值得优化;如果分析显示实际的热点,只考虑它。事实上,大多数应用程序使用反射JSON映射器,并且它们的瓶颈在其他地方(通常是I / O)。您使用的StringBuilder
方法是最有效的方法,您可以在Java中执行此操作而无需手动操作字符数组,并且它甚至比我自己更远(我使用它) String#format()
)。
为了清晰起见,请编写代码。目前的版本很好。