我正在使用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正确吗?
P.S。方法参数的数组是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);
答案 0 :(得分:1)
收集到具有相同值的嵌套地图不是很有用。结果Map<Boolean, Map<String, Boolean>>
只能有两个键true
和false
。当您在其上调用get(true)
时,会得到一个Map<String, Boolean>
,其中所有字符串键都冗余地映射到true
。同样,get(false)
将为您提供一个所有值均为false
的you map。
在我看来,你确实想要
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
调用将不取决于{{1}的大小}。
答案 1 :(得分:0)
我设法解决了我的问题。我的类型不匹配,因此工作代码为:
private Map<Boolean, 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(collectingAndThen(
groupingBy(Map.Entry::getValue, toMap(Map.Entry::getKey, Map.Entry::getValue)),
Collections::<Boolean, Map<String, Boolean>> unmodifiableMap));
}