给定一个目录名列表,我想生成目录中所有文件到其内容的映射。
有关更明确实施的建议吗?
Map<File, String> map = new HashMap<>();
Arrays.stream(filenames)
.map(s -> FileUtils.listFiles(new File(rootdir, s), new RegexFileFilter(".*"), DirectoryFileFilter.DIRECTORY))
.flatMap(Collection::stream)
.forEach(f -> {
try {
map.put(f, FileUtils.readFileToString(f));
}
catch (IOException e) {
e.printStackTrace();
}
});
return map;
`
答案 0 :(得分:3)
您应该使用Collectors.toMap
:
Map<File, String> map = Arrays.stream(filenames)
.map(s -> FileUtils.listFiles(new File(rootdir, s), new RegexFileFilter(".*"), DirectoryFileFilter.DIRECTORY))
.flatMap(Collection::stream)
.collect(Collectors.toMap(
Function.identity(),
f-> {
try { return FileUtils.readFileToString(f); }
catch (IOException ioe) { return null; }
}
));
它的第一个参数是键映射函数。未修改的文件应该用作键,因此我们可以使用标识功能
它的第二个参数是值映射函数,我们将File
映射到它们的内容。
请注意,我的值映射函数会生成null
个值,并且在无法读取文件的内容时不会输出任何错误。考虑使用其他答案之一,除非您确信IOException
永远不会发生。
答案 1 :(得分:2)
你的做法真的不错,但我想知道在你的情况下使用流是否是获得更明确代码的最佳方式。
Aaron解决方案稍微更直,更“流式”,因为它将地图收集为终端操作,但它也会在抛出IOException
的情况下更改原始逻辑。
没有流的版本显得非常直接:
Map<File, String> map = new HashMap<>();
for (String filename : filenames) {
for (File file : FileUtils.listFiles(new File(rootdir, filename), new RegexFileFilter(".*"), DirectoryFileFilter.DIRECTORY)) {
try {
map.put(file, FileUtils.readFileToString(file));
} catch (IOException e) {
// log exception
}
}
}
编辑:tsolakp与stream的解决方案非常好,即使它比使用经典循环的方式更不直接。
这是一个较轻的版本
我认为不需要在流内部使用Optional
。它是“我们的”流,所以我们掌握了我们放入的内容(这里null
表示失败案例)
此外,包括map()
处理中的代码可能看起来不那么“功能”但它仍然是可读的,我发现它更适合阅读间接。
import java.util.AbstractMap.SimpleImmutableEntry;
// ...
Map<File, String> map = Arrays.stream(filenames)
.flatMap( s -> FileUtils.listFiles( new File(rootdir, s), new RegexFileFilter(".*"), DirectoryFileFilter.DIRECTORY ).stream() )
.map( f -> {
try{
return new SimpleImmutableEntry<>(f, FileUtils.readFileToString(f) );
}catch(IOException e){
//log exception
return null;
}
}
)
.filter(Objects::nonNull)
.collect(Collectors.toMap(SimpleImmutableEntry::getKey, SimpleImmutableEntry::getValue));
答案 2 :(得分:1)
“更明确的实施”是基于意见的。对于我使用像@davidxxx这样的普通循环来说,确实是首选方式。 当然,您也可以使用Java流,但是缺少处理异常将使您的代码使用try / catch语句难看。 一种选择是将try / catch移动到单独的方法或实用程序类中,并使流表达式更清晰,如下所示:
Map<File, String> map = Arrays.stream(filenames)
.flatMap( s -> FileUtils.listFiles( new File(rootdir, s), new RegexFileFilter(".*"), DirectoryFileFilter.DIRECTORY ).stream() )
.map( f -> new AbstractMap.SimpleImmutableEntry<>(f, read(f) ) )
.filter( e -> e.getValue().isPresent() )
.collect( Collectors.toMap( e -> e.getKey(), e -> e.getValue().get() ) );
private Optional<String> read(File f){
try{
return Optional.of( FileUtils.readFileToString(f) );
}catch(IOException e){
//log exception
return Optional.empty();
}
}