我正在使用JCIFS比较文件夹(接收方和发送方)中的文件。比较期间可能会发生两种情况:
-文件在接受者处不存在
-文件存在于接受者处
我需要一张地图,比较的文件按提到的两种类型分组,因此我可以复制不存在的文件或检查文件大小和现有文件的修改日期...
我想使用lambda和流制作它,因为我将在不久的将来使用并行流,这也很方便... \
我设法制作了一个可行的原型方法,用于检查文件是否存在并创建映射:
private Map<String, Boolean> compareFiles(String[] acceptor, String[] sender) {
return Arrays.stream(sender)
.map(s -> new AbstractMap.SimpleEntry<>(s, Stream.of(acceptor).anyMatch(s::equals)))
Map.Entry::getValue)));
.collect(collectingAndThen(
toMap(Map.Entry::getKey, Map.Entry::getValue),
Collections::<String,Boolean> unmodifiableMap));
}
但我无法按地图值添加更高级别的分组...
我有一段不起作用的代码:
private Map<String, Boolean> compareFiles(String[] acceptor, String[] sender) {
return Arrays.stream(sender)
.map(s -> new AbstractMap.SimpleEntry<>(s, Stream.of(acceptor).anyMatch(s::equals)))
.collect(groupingBy(
Map.Entry::getValue,
groupingBy(Map.Entry::getKey, Map.Entry::getValue)));
}
}
我的代码无法编译,因为我错过了一些非常重要的内容。有人可以帮我解释一下如何使此lambda正确吗?
附言方法参数的数组是SmbFiles samba目录:
private final String master = "smb://192.168.1.118/mastershare/";
private final String node = "smb://192.168.1.118/nodeshare/";
SmbFile masterDir = new SmbFile(master);
SmbFile nodeDir = new SmbFile(node);
Map<Boolean, <Map<String, Boolean>>> resultingMap = compareFiles(masterDir, nodeDir);
最佳答案
收集到具有相同值的嵌套地图不是很有用。结果Map<Boolean, Map<String, Boolean>>
只能有两个键,分别是true
和false
。当您在其上调用get(true)
时,会得到一个Map<String, Boolean>
,其中所有字符串键都冗余地映射到true
。同样,get(false)
将为您映射所有值均为false
的地图。
对我来说,看起来你真的想要
private Map<Boolean, Set<String>> compareFiles(String[] acceptor, String[] sender) {
return Arrays.stream(sender)
.collect(partitioningBy(Arrays.asList(acceptor)::contains, toSet()));
}
其中
get(true)
为您提供一组所有字符串,其中谓词评估为true
,反之亦然。partitioningBy
是groupingBy
键的boolean
的优化版本。请注意,
Stream.of(acceptor).anyMatch(s::equals)
是Stream功能的过度使用。 Arrays(acceptor).contains(s)
更简单,当用作Arrays.asList(acceptor)::contains
之类的谓词时,表达式Arrays.asList(acceptor)
仅会被求值一次,并且每次求值时调用contains
的函数都会传递给收集器。当
acceptor
变大时,您不应该考虑并行处理,而应使用哈希查找替换线性搜索private Map<Boolean, Set<String>> compareFiles(String[] acceptor, String[] sender) {
return Arrays.stream(sender)
.collect(partitioningBy(new HashSet<>(Arrays.asList(acceptor))::contains, toSet()));
}
同样,
new HashSet<>(Arrays.asList(acceptor))
的准备工作仅完成一次,而为contains
的每个元素完成的sender
调用将不再取决于acceptor
的大小。