Java 如何简化流式管道

Java 如何简化流式管道,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我认为我的代码需要改进。我在流的filter()和map()阶段中都使用objectallSummaryTSTLog,因此我必须调用File.listFiles两次: public static List<Test> ParserPath(List<String> allLogPath) { FilenameFilter filter = new MyFilter("Summary_TSTLog"); return allLogPath.paralle

我认为我的代码需要改进。我在流的
filter()
map()
阶段中都使用object
allSummaryTSTLog
,因此我必须调用
File.listFiles
两次:

public static List<Test> ParserPath(List<String> allLogPath) {

    FilenameFilter filter = new MyFilter("Summary_TSTLog");

    return allLogPath.parallelStream().filter(path -> {
        File testPath = new File(path);

        if (!testPath.isDirectory()) {
            MyLog.log.info("test path : [" + path + "] is not exist, continue");
            return false;
        }

        File[] allSummaryTSTLog = testPath.listFiles(filter);
        if (allSummaryTSTLog == null || allSummaryTSTLog.length == 0) {
            MyLog.log.info("test path : [" + path + "] has no Summary_TSTLog files");
            return false;
        }
        return true;
    }).map(path -> {
        String[] nameTempStr = path.split("\\\\");
        String testName = nameTempStr[nameTempStr.length - 1];

        File[] allSummaryTSTLog = new File(path).listFiles(filter);

        return new Test(testName, Arrays.asList(allSummaryTSTLog));
    }).collect(Collectors.toList());
}
publicstaticlist解析器路径(List-allLogPath){
FilenameFilter filter=newmyfilter(“Summary_TSTLog”);
返回allLogPath.parallelStream().filter(路径->{
文件testPath=新文件(路径);
如果(!testPath.isDirectory()){
MyLog.log.info(“测试路径:[“+path+”]不存在,继续”);
返回false;
}
文件[]allSummaryTSTLog=testPath.listFiles(过滤器);
if(allSummaryTSTLog==null | | allSummaryTSTLog.length==0){
MyLog.log.info(“测试路径:[“+path+”]没有摘要日志文件”);
返回false;
}
返回true;
}).map(路径->{
字符串[]nameTempStr=path.split(“\\”);
字符串testName=nameTempStr[nameTempStr.length-1];
File[]allSummaryTSTLog=新文件(路径).listFiles(过滤器);
返回新测试(testName,Arrays.asList(allSummaryTSTLog));
}).collect(Collectors.toList());
}

如何调用
File.listFiles()
只创建一次
allSummaryTSTLog
。不要使用
文件

此外,对于您想做什么,根本没有任何线索(您
MyFilter
做什么?什么是
Test
?)

使用类似以下内容:

final BiPredicate<Path, BasicFileAttributes> predicate = (path, attrs) -> {
    return attrs.isRegularFile()
        && path.getFileName().toString().equals(something);
};

try (
    final Stream<Path> stream = Files.find(baseDir, filter);
) {
    // work with the stream
}
final-BiPredicate谓词=(路径,属性)->{
返回attrs.isRegularFile()
&&path.getFileName().toString().equals(某物);
};
试一试(
final Stream=Files.find(baseDir,filter);
) {
//随波逐流
}
因为你的帖子没有关于你想做什么的线索,所以这是最好的


有关如何获取路径的信息,请参见路径获取()。以及java.nio.file的文档。

通常希望根据某些计算筛选流元素,然后在以后的管道阶段重用该计算的结果。当然,您可以在稍后的管道阶段重新计算该结果,但如果您不想这样做,这是非常合理的。如果流元素本身无法存储这些计算结果,并且您不想重新计算它们,那么您必须创建一个帮助器类来将原始元素和计算结果带到流中

我查看了管道中使用的数据,下面是我提出的helper类:

static class FileInfo {
    final String fullName;
    final String lastName;
    final File[] allSummaryTSTLog;

    FileInfo(String n, FilenameFilter fnf) {
        fullName = n;
        String[] tmp = n.split("\\\\");
        lastName = tmp[tmp.length - 1];
        allSummaryTSTLog = new File(n).listFiles(fnf);
    }
}
注意,为了简洁起见,我在这里做了一些欺骗。首先,我没有显式地检查
isDirectory
,而是利用了
File.listFiles
文件
不是目录时返回null的事实。我也没有费心区分给定文件名不是目录的情况和它是目录但不包含匹配文件的情况。(不过,这对你来说可能意义重大;我不确定。)

最后,我在构造函数中进行文件名路径拆分,以便在必要时可以使用名称的最后一个组件。拆分需要一个局部变量。如果在以后的管道阶段进行拆分,则局部变量将强制使用语句lambda而不是表达式lambda,这将使事情变得更加麻烦。折衷的办法是,我们可能最终会对最终被过滤掉的文件进行路径名拆分,但这似乎并不是一笔过多的费用

有了此帮助器类,可以按如下方式重写管道:

 static List<Test> parserPath(List<String> allLogPath) {
    FilenameFilter filter = new MyFilter("Summary_TSTLog");
    return allLogPath.parallelStream()
        .map(str -> new FileInfo(str, filter))
        .filter(fi -> fi.allSummaryTSTLog != null && fi.allSummaryTSTLog.length > 0)
        .map(fi -> new Test(fi.lastName, Arrays.asList(fi.allSummaryTSTLog)))
        .collect(toList());
}
static List parserPath(List allLogPath){
FilenameFilter filter=newmyfilter(“Summary_TSTLog”);
返回allLogPath.parallelStream()
.map(str->newfileinfo(str,过滤器))
.filter(fi->fi.allSummaryTSTLog!=null&&fi.allSummaryTSTLog.length>0)
.map(fi->newtest(fi.lastName,Arrays.asList(fi.allSummaryTSTLog)))
.collect(toList());
}
在第一个管道阶段,我们将传入流元素映射到助手类的实例中。后续阶段可以使用helper类中的数据,而无需重新计算它。

我猜他的意思是“更简单”,而不是“取样器”