Java 如何在功能上处理分割流
给定以下代码,如何将其简化为单个功能行Java 如何在功能上处理分割流,java,java-8,functional-programming,java-stream,Java,Java 8,Functional Programming,Java Stream,给定以下代码,如何将其简化为单个功能行 // DELETE CSV TEMP FILES final Map<Boolean, List<File>> deleteResults = Stream.of(tmpDir.listFiles()) .filter(tempFile -> tempFile.getName().endsWith(".csv")) .collect(Collectors.part
// DELETE CSV TEMP FILES
final Map<Boolean, List<File>> deleteResults = Stream.of(tmpDir.listFiles())
.filter(tempFile -> tempFile.getName().endsWith(".csv"))
.collect(Collectors.partitioningBy(File::delete));
// LOG SUCCESSES AND FAILURES
deleteResults.entrySet().forEach(entry -> {
if (entry.getKey() && !entry.getValue().isEmpty()) {
LOGGER.debug("deleted temporary files, {}",
entry.getValue().stream().map(File::getAbsolutePath).collect(Collectors.joining(",")));
} else if (!entry.getValue().isEmpty()) {
LOGGER.debug("failed to delete temporary files, {}",
entry.getValue().stream().map(File::getAbsolutePath).collect(Collectors.joining(",")));
}
});
这是我遇到的一个常见模式,我有一个流,我想过滤这个流,根据这个过滤器创建两个流,然后我可以对流a做一件事,对流B做另一件事。这是反模式吗,或者它是以某种方式被支持的?如果您特别不希望显式变量引用中间映射,那么您可以只链接操作:
.collect(Collectors.partitioningBy(File::delete))
.forEach((del, files) -> {
if (del) {
LOGGER.debug(... files.stream()...);
} else {
LOGGER.debug(... files.stream()...);
});
如果您特别不希望显式变量引用中间映射,那么您可以只链接操作:
.collect(Collectors.partitioningBy(File::delete))
.forEach((del, files) -> {
if (del) {
LOGGER.debug(... files.stream()...);
} else {
LOGGER.debug(... files.stream()...);
});
若要将任一类别的所有文件记录在一起,在所有元素都已知之前,无法将它们收集到保存它们的数据结构中。不过,您可以简化代码:
Stream.of(tmpDir.listFiles())
.filter(tempFile -> tempFile.getName().endsWith(".csv"))
.collect(Collectors.partitioningBy(File::delete,
Collectors.mapping(File::getAbsolutePath, Collectors.joining(","))))
.forEach((success, files) -> {
if (!files.isEmpty()) {
LOGGER.debug(success? "deleted temporary files, {}":
"failed to delete temporary files, {}",
files);
}
});
这不会将文件收集到列表中,而是首先收集到后续日志记录操作所需的字符串中。对于这两种情况,日志记录操作也是相同的,但只在消息中有所不同
不过,最有趣的是删除文件失败的原因,布尔值无法说明这一点。自Java 7以来,nio包提供了更好的选择:
创建助手方法
public static String deleteWithReason(Path p) {
String problem;
IOException ioEx;
try {
Files.delete(p);
return "";
}
catch(FileSystemException ex) {
problem = ex.getReason();
ioEx = ex;
}
catch(IOException ex) {
ioEx = ex;
problem = null;
}
return problem!=null? problem.replaceAll("\\.?\\R", ""): ioEx.getClass().getName();
}
像这样使用它
Files.list(tmpDir.toPath())
.filter(tempFile -> tempFile.getFileName().toString().endsWith(".csv"))
.collect(Collectors.groupingBy(YourClass::deleteWithReason,
Collectors.mapping(p -> p.toAbsolutePath().toString(), Collectors.joining(","))))
.forEach((failure, files) ->
LOGGER.debug(failure.isEmpty()? "deleted temporary files, {}":
"failed to delete temporary files, "+failure+ ", {}",
files)
);
如果您想这样称呼它,缺点是如果失败的文件有不同的失败原因,则不会为所有失败的文件生成一个条目。但是,如果您想记录它们,并说明无法删除它们的原因,那么这显然是不可避免的
请注意,如果要从失败中排除“被其他人同时删除”,只需使用Files.deleteIfExistsp而不是Files.deletep,并且已被删除将被视为成功。如果要将任一类别的所有文件记录在一起,在所有元素都已知之前,无法将它们收集到保存它们的数据结构中。不过,您可以简化代码:
Stream.of(tmpDir.listFiles())
.filter(tempFile -> tempFile.getName().endsWith(".csv"))
.collect(Collectors.partitioningBy(File::delete,
Collectors.mapping(File::getAbsolutePath, Collectors.joining(","))))
.forEach((success, files) -> {
if (!files.isEmpty()) {
LOGGER.debug(success? "deleted temporary files, {}":
"failed to delete temporary files, {}",
files);
}
});
这不会将文件收集到列表中,而是首先收集到后续日志记录操作所需的字符串中。对于这两种情况,日志记录操作也是相同的,但只在消息中有所不同
不过,最有趣的是删除文件失败的原因,布尔值无法说明这一点。自Java 7以来,nio包提供了更好的选择:
创建助手方法
public static String deleteWithReason(Path p) {
String problem;
IOException ioEx;
try {
Files.delete(p);
return "";
}
catch(FileSystemException ex) {
problem = ex.getReason();
ioEx = ex;
}
catch(IOException ex) {
ioEx = ex;
problem = null;
}
return problem!=null? problem.replaceAll("\\.?\\R", ""): ioEx.getClass().getName();
}
像这样使用它
Files.list(tmpDir.toPath())
.filter(tempFile -> tempFile.getFileName().toString().endsWith(".csv"))
.collect(Collectors.groupingBy(YourClass::deleteWithReason,
Collectors.mapping(p -> p.toAbsolutePath().toString(), Collectors.joining(","))))
.forEach((failure, files) ->
LOGGER.debug(failure.isEmpty()? "deleted temporary files, {}":
"failed to delete temporary files, "+failure+ ", {}",
files)
);
如果您想这样称呼它,缺点是如果失败的文件有不同的失败原因,则不会为所有失败的文件生成一个条目。但是,如果您想记录它们,并说明无法删除它们的原因,那么这显然是不可避免的
请注意,如果要从失败中排除“被其他人同时删除”,只需使用Files.deleteIfExistsp而不是Files.deletep,并且已删除将被视为成功。使用map。或者,如果你真的愿意,可以使用分区。你可能的重复不是通过过滤而是通过分组创建两个流,在你的例子中是通过分区;你不可能真的把一条河流一分为二——你必须把它分成两部分;这不是一个反模式,这里显示的答案正是使用map。或者,如果你真的愿意,可以使用分区。你可能的重复不是通过过滤而是通过分组创建两个流,在你的例子中是通过分区;你不可能真的把一条河流一分为二——你必须把它分成两部分;这不是一个反模式,这里给出的答案正是如此