我正在使用 JCIFS 比较文件夹(接受者和发送者)中的文件。在比较过程中可能会出现两种情况: - 接受者处不存在文件 - 文件存在于接受者
我需要一张 map ,其中比较的文件按提到的两种类型分组,因此我可以复制不存在的文件或检查现有文件的大小和修改日期......
我想使用 lambda 和流来实现它,因为我将在不久的将来使用并行流,而且它也很方便...\
我已经设法制作了一个工作原型(prototype)方法来检查文件是否存在并创建一个 map :
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));
}
但我无法按 map 值添加更高级别的分组...
我有这样一段无法工作的代码:
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)
会给你一张 map ,其中所有值都是 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
的大小不再。
关于java - 如何使用 lambda 正确制作多级 map ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57199656/