Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,如何使用结果列表本身的属性筛选目录列表?_Java_Java 8_Functional Programming_Java Stream - Fatal编程技术网

在Java中,如何使用结果列表本身的属性筛选目录列表?

在Java中,如何使用结果列表本身的属性筛选目录列表?,java,java-8,functional-programming,java-stream,Java,Java 8,Functional Programming,Java Stream,我有一个名为/home/ftp的目录,其中包含如下子目录: dir1 dir2 dir3 dir1.ok (this is just an empty file) dir3.ok (this is just an empty file) 代码应该只处理目录下的文件,这些目录下有一个对应的。文件。因此,例如,在本例中,代码应该选择那些在dir1和dir3下找到的文件进行处理,而不是dir2 我可以用“正常”的方式: List List=Arrays.asList(新文件(“/home/ftp”)

我有一个名为
/home/ftp
的目录,其中包含如下子目录:

dir1
dir2
dir3
dir1.ok (this is just an empty file)
dir3.ok (this is just an empty file)
代码应该只处理目录下的文件,这些目录下有一个对应的
文件。
因此,例如,在本例中,代码应该选择那些在
dir1
dir3
下找到的文件进行处理,而不是
dir2

我可以用“正常”的方式:

List List=Arrays.asList(新文件(“/home/ftp”).List());
Set=newhashset();
List dirToProcess=new ArrayList();
用于(字符串名称:列表){
name=name.contains(“.ok”)?name.substring(0,name.indexOf(“.ok”)):name;
如果(!set.add(name)){
dirToProcess.add(名称);
}       
}
//现在,dirToProcess包含应该处理的目录名

但是我真的想使用流来使用函数式Java(我使用的是Java8)来实现这一点。我如何重构这段代码来实现它?

你让自己更难做到这一点。如果您知道该文件将包含
。确定
只需按此筛选,然后将其收集到新列表中,然后在尝试获取不包含
的文件时删除扩展名。确定

List<String> filteredList = list.stream()
        .filter(s -> s.endsWith(".ok"))
        .collect(Collectors.toList());

    filteredList.forEach(s -> {
        String name = s.substring(0, s.indexOf(".ok"));
        //You can handle it here
    });
List filteredList=List.stream()
.filter(s->s.endsWith(“.ok”))
.collect(Collectors.toList());
filteredList.forEach(s->{
字符串名称=s.substring(0,s.indexOf(“.ok”);
//你可以在这里处理
});

如果要使用streams转换当前方法,可以执行以下操作:

List<String> result = 
          Arrays.stream(new File("/home/ftp").list())
                .map(name -> name.endsWith(".ok") ? name.substring(0, name.indexOf(".ok")) : name)
                //.distinct()
                .collect(toList());
列表结果=
Arrays.stream(新文件(“/home/ftp”).list())
.map(name->name.endsWith(“.ok”)?name.substring(0,name.indexOf(“.ok”):name)
//.distinct()
.collect(toList());

另一方面,使用API、一些示例等可能有更好的方法来实现这一点。

我认为您期望的输出是:

List<String> dirToProcess = list.stream()
                .filter(name -> name.contains(".ok") && list.contains(name.substring(0, name.indexOf(".ok"))))
                .map(name -> name.substring(0, name.indexOf(".ok")))
                .collect(Collectors.toList());
List dirToProcess=List.stream()
.filter(name->name.contains(.ok”)&&list.contains(name.substring(0,name.indexOf(.ok)))
.map(name->name.substring(0,name.indexOf(“.ok”))
.collect(Collectors.toList());

另一种方法是使用模式regex

Pattern hasOk = Pattern.compile("\\b.ok");
List<String> list = Arrays.asList("dir1.ok (this is just an empty file)","dir1.o","dir3");
List<String> result = list.stream()
            .filter(hasOk.asPredicate()) //or  .map(name -> hasOk.matcher(name).find()?name.substring(0,name.indexOf(".ok")):name)
            .collect(Collectors.toList());
Pattern hasOk=Pattern.compile(\\b.ok”);
List List=Arrays.asList(“dir1.ok(这只是一个空文件)”、“dir1.o”、“dir3”);
列表结果=List.stream()
.filter(hasOk.asPredicate())//或.map(name->hasOk.matcher(name).find()?name.substring(0,name.indexOf(“.ok”)):name)
.collect(Collectors.toList());

您可以将其分为两个步骤

@Test
public void should_return_dirs_with_corresponding_ok_file() {
    List<String> list = Arrays.asList("dir1.ok", "dir1", "dir2", "dir3.ok");

    //find all files ending with .ok and extract prefix
    List<String> okEndingFilesPrefix = list.stream()
        .filter(s -> s.endsWith(".ok"))
        //save those dirs prefix
        .map(s -> s.replace(".ok", ""))
        .collect(Collectors.toList());

    //filter existing dirs if they have corresponding file ending with ok, from previous step.
    List<String> dirsWithCorrespondingOkEndingFile = list.stream()
        .filter(s -> okEndingFilesPrefix.contains(s))
        .collect(Collectors.toList());

    assertEquals(dirsWithCorrespondingOkEndingFile, Lists.newArrayList("dir1"));
}
@测试
public void应返回\u dirs\u以及相应的\u ok\u文件(){
List List=Arrays.asList(“dir1.ok”、“dir1”、“dir2”、“dir3.ok”);
//查找以.ok结尾的所有文件并提取前缀
List okEndingFilesPrefix=List.stream()
.filter(s->s.endsWith(“.ok”))
//保存那些dirs前缀
.map(s->s.replace(“.ok”和“))
.collect(Collectors.toList());
//从上一步筛选现有目录,如果它们具有以ok结尾的相应文件。
List dirswithcorrespondingKendingFile=List.stream()
.filter->okEndingFilesPrefix.contains
.collect(Collectors.toList());
assertEquals(dirswithcorrespondingKendingFile,Lists.newArrayList(“dir1”));
}
如果您希望以一行程序的形式执行此操作,则可以使用分组函数。 在我看来,这在Java中看起来并不好

@Test
public void should_return_dirs_with_corresponding_ok_file_with_grouping() {
    List<String> list = Arrays.asList("dir1.ok", "dir1", "dir2", "dir3.ok");


    List<String> dirsWithCorrespondingOkEndingFile = list.stream()
        //create "touple" with dir name/file name without .ok suffix as key.
        .map(s -> Pair.of(s.replaceAll(".ok", ""), s))
        // group by key
        .collect(
            Collectors.groupingBy(
                Pair::getKey, Collectors.toSet()
            ))
        //once again to stream
        .entrySet()
        .stream()
        // filter elements that has dir and file with .ok suffix
        .filter(entry -> entry.getValue().size() == 2)
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());

    assertEquals(dirsWithCorrespondingOkEndingFile, Lists.newArrayList("dir1"));
}
@测试
public void应返回\u dirs\u和\u对应的\u ok\u file\u和\u grouping(){
List List=Arrays.asList(“dir1.ok”、“dir1”、“dir2”、“dir3.ok”);
List dirswithcorrespondingKendingFile=List.stream()
//创建“touple”,目录名/文件名不带.ok后缀作为键。
.map(s->Pair.of(s.replaceAll(“.ok”,”),s))
//按键分组
.收集(
收集者分组(
Pair::getKey,Collectors.toSet()
))
//再次流
.entrySet()
.stream()
//具有dir和带有.ok后缀的文件的筛选器元素
.filter(条目->条目.getValue().size()=2)
.map(map.Entry::getKey)
.collect(Collectors.toList());
assertEquals(dirswithcorrespondingKendingFile,Lists.newArrayList(“dir1”));
}

那么这不会返回
dir1
两次吗?@nullpointer我已经包含了用于删除重复项的独特调用,但目前已注释掉,我认为如果需要,OP将取消注释。我今天大部分时间都在打电话,所以没有太多的工作考虑我的答案…第二个选择在Scala中可能会更好。
@Test
public void should_return_dirs_with_corresponding_ok_file_with_grouping() {
    List<String> list = Arrays.asList("dir1.ok", "dir1", "dir2", "dir3.ok");


    List<String> dirsWithCorrespondingOkEndingFile = list.stream()
        //create "touple" with dir name/file name without .ok suffix as key.
        .map(s -> Pair.of(s.replaceAll(".ok", ""), s))
        // group by key
        .collect(
            Collectors.groupingBy(
                Pair::getKey, Collectors.toSet()
            ))
        //once again to stream
        .entrySet()
        .stream()
        // filter elements that has dir and file with .ok suffix
        .filter(entry -> entry.getValue().size() == 2)
        .map(Map.Entry::getKey)
        .collect(Collectors.toList());

    assertEquals(dirsWithCorrespondingOkEndingFile, Lists.newArrayList("dir1"));
}