Gib*_*tar 14 java java-8 java-stream
我正在寻找一种以Stream干净的方式优化处理的方法.
我有类似的东西:
try (Stream<Path> stream = Files.list(targetDir)) {
Map<String, List<Path>> targetDirFilteredAndMapped = stream.parallel()
.filter(path -> sd.containsKey(md5(path)))
.collect(Collectors.groupingBy(path -> md5(path)));
} catch (IOException ioe) { // manage exception }
Run Code Online (Sandbox Code Playgroud)
由于该md5功能非常昂贵,我想知道是否有办法每个文件只调用一次.
有什么建议?
Era*_*ran 12
您可以创建一些PathWrapper包含Path实例及其对应的对象md5(path).
public class PathWrapper
{
Path path;
String md5; // not sure if it's a String
public PathWrapper(Path path) {
this.path = path;
this.md5 = md5(path);
}
public Path getPath() {return path;}
public String getMD5() {return md5;}
}
Run Code Online (Sandbox Code Playgroud)
然后将您的信息流映射到Stream<PathWrapper>:
try (Stream<Path> stream = Files.list(targetDir)) {
Map<String, List<Path>> targetDirFilteredAndMapped =
stream.parallel()
.map(PathWrapper::new)
.filter(path -> sd.containsKey(path.getMD5()))
.collect(Collectors.groupingBy(PathWrapper::getMD5,
Collectors.mapping(PathWrapper::getPath,
Collectors.toList())));
} catch (IOException ioe) { /* manage exception */ }
Run Code Online (Sandbox Code Playgroud)
如果md5操作真正主导了性能,您可以考虑在此处取消过滤,然后删除不匹配的组:
try(Stream<Path> stream = Files.list(targetDir)) {
Map<String, List<Path>> targetDirFilteredAndMapped = stream.parallel()
.collect(Collectors.groupingBy(p -> md5(p), HashMap::new, Collectors.toList()));
targetDirFilteredAndMapped.keySet().retainAll(sd.keySet());
} catch (IOException ioe) {
// manage exception
}
Run Code Online (Sandbox Code Playgroud)
当然,这暂时需要更多内存.如果这是一个问题,使用更复杂的解决方案,如其他答案所示,是不可避免的.
创建专用类的另一种collect方法是直接使用该方法,您将负责md5在累加器中进行计算以及组合器将在何处合并条目.
try (Stream<Path> stream = Files.list(targetDir)) {
Map<String, List<Path>> targetDirFilteredAndMapped =
stream.parallel()
.collect(HashMap::new,
(m, p) -> {
String res = md5(p);
if(sd.containsKey(res)) {
m.computeIfAbsent(res, k -> new ArrayList<>()).add(p);
}
},
(m1, m2) -> m2.forEach((k, v) -> m1.computeIfAbsent(k, k2 -> new ArrayList<>()).addAll(v)));
} catch (IOException ioe) {
// manage exception
}
Run Code Online (Sandbox Code Playgroud)
正如@Holger指出的那样,您可以通过避免使用更好的合并函数创建新列表来优化它:
(m1, m2) -> m2.forEach((k,v) -> m1.merge(k, v, (l1,l2) -> { l1.addAll(l2); return l1; }))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1569 次 |
| 最近记录: |