当前位置: 首页 > 知识库问答 >
问题:

如何在功能上处理分割流

薛鹏飞
2023-03-14

给定以下代码,如何将其简化为单个功能行?

    // 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做另一件事。这是一个反模式,还是以某种方式得到支持?

共有2个答案

杜阳炎
2023-03-14

若要将这两个类别的所有文件记录在一起,在所有元素都已知之前,无法将它们收集到保存它们的数据结构中。不过,您可以简化代码:

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);
    }
});

这不会将文件收集到List中,而是首先收集到预期的String中,以便进行后续日志记录操作。两种情况下的日志记录操作也是相同的,但仅在消息中有所不同。

尽管如此,最有趣的事情是为什么删除文件失败,boolean并没有说明这一点。因为Java

创建助手方法

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)
);

如果您想这样称呼它,缺点是如果失败的文件有不同的失败原因,则不会为所有失败的文件生成一个条目。但如果你想把它们记录下来,说明为什么不能删除,这显然是不可避免的。

请注意,如果要从失败中排除“被其他人同时删除”,只需使用文件即可。deleteIfExists(p)而不是文件。删除(p)并且已经被删除将被视为成功。

周兴朝
2023-03-14

如果您特别不希望显式变量引用中间映射,那么您可以只链接操作:

.collect(Collectors.partitioningBy(File::delete))
.forEach((del, files) -> {
    if (del) {
        LOGGER.debug(... files.stream()...);
    } else {
        LOGGER.debug(... files.stream()...);
    });
 类似资料:
  • 问题内容: 我想从特定的行号中拆分一个400k行长的日志文件。 对于这个问题,让我们将其设为任意数字300k。 是否有Linux命令允许我执行此操作( 在脚本内 )? 我知道可以按大小或行号将文件分成相等的部分,但这不是我想要的。我想要一个文件中的前300k,第二个文件中的最后100k。 任何帮助,将不胜感激。谢谢! 再三考虑,这将更适合于超级用户或服务器故障站点。 问题答案: file_name

  • 目前需要用whsiper做语音转录服务,whisper限制25M的大小,请问该如何做这个事情? 目前的需求是 Android iOS Web 都需要这个功能, 目前有几种方案: 方案1 做一个音频分割服务器,然后在做一个转录服务。前端拿到语音文件之后,把语音文件传给音频分割服务器,分割服务器根据波形进行分割,分割完之后传给转录接口。 问题: 这样做的话是不是会造成语音上传多次导致时间较长的问题,因

  • 问题内容: 我想表达一个可以分割的函数。我以为我可以这样做: 其中本身需要的类型。但是,这不起作用,因为您不能通过as 。请参阅:https : //golang.org/doc/faq#convert_slice_of_interface,它指出[] interface {}的表示形式是不同的。 上面golang.org链接中提供的建议建议从该切片中重建一个新的接口切片。但是,在我想调用该函数的

  • 本文向大家介绍PHP大文件切割上传功能实例分析,包括了PHP大文件切割上传功能实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了PHP大文件切割上传功能。分享给大家供大家参考,具体如下: 大家都知道php上传文件有限制,如果没有修改过php.ini文件的话,默认的上传大小限制为2M,那么该如何上传大文件了,比如说上传一个1G多的大文件,可以使用大文件切割上传的方式来解决。 何为大文件

  • 问题内容: 这是我需要分割的字符串。 我尝试了这个 但是没有用。 如何拆分此字符串… 问题答案: 首先,你不能在有问题的地方输入字符串 这应该替换为 因为反斜杠也需要转义。 最后,你需要执行以下操作来拆分它们: 希望这可以帮助。

  • 本文向大家介绍分享php多功能图片处理类,包括了分享php多功能图片处理类的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了多功能php图片处理类,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家学习PHP程序设计有所帮助。