是否可以用 Stream API 替换不同集合上的嵌套循环

Is it possible to replace nested loops on different collections with Stream API

我想知道是否可以在 Java 8?

中使用 java.utils.stream 重写嵌套的 for 循环

这是我正在使用的示例数据类型:

class Folder {
  private final String name;
  private final Integer itemCound;

  Folder(String name, Integer itemCount) {
    this.name = name;
    this.itemCount = itemCount;
  }

  public String getName() { return this.name; }
  public Integer getItemCount() { return this.itemCount; }
}

下面是实际代码:

List<Folder> oldFolders = new ArrayList<>();
List<Folder> newFolders = new ArrayList<>();

// Fill folder collections with sample data...
oldFolders.add(new Folder("folder1", 2));
oldFolders.add(new Folder("folder2", 4));
newFolders.add(new Folder("folder1", 0));
newFolders.add(new Folder("folder2", 100));

// This part should be rewrited using streams
for (Folder newFolder : newFolders) {
  for (Folder oldFolder : oldFolders) {
    if (newFolder.getName().equals(oldFolder.getName()) 
        && !newFolder.getItemCount().equals(oldFolder.getItemCount())) {
      // do stuff...    
    }
  }
}

P.S:我在 SO 上看到过其他问题,但它们都有 1 个集合或一个具有自己的嵌套集合而不是两个不同集合的集合就像我的例子。

提前致谢!

是的,你可以:

newFolders.forEach((newFolder) -> {
    oldFolders.forEach((oldFolder) -> {
        if (newFolder.getName().equals(oldFolder.getName()) 
        && !newFolder.getItemCount().equals(oldFolder.getItemCount())) {
           // do stuff...    
        }
     })
  })

编辑:但是正如@Kayaman 在下面的评论中提到的那样,这不一定比使用嵌套 for 循环更好。

这是一本关于何时应该和不应该考虑使用流的好书:

除非您可以并行化第一次迭代(在此示例中已注释),否则公平地说,这并没有太大的改进

List<String> oldList = new ArrayList<>();
List<String> newList = new ArrayList<>();

oldList
    //.stream()
    //.parallel() 
    .forEach(s1 ->
    newList
        .stream()
        .filter(s2 -> s1.equals(s2)) //could become a parameter Predicate
        .forEach(System.out::println) //could become a parameter Consumer
);

filter 和他的 Predicate 替换 if 然后在其上执行一个方法。

这将提供一个动态的解决方案,为 filterforEach 方法提供不同的 PredicateConsumer。这将是进行此转换的唯一原因。

试试这个:

newFolders.stream().filter(newFolder -> 
            oldFolders
                    .stream()
                    .anyMatch(oldFolder-> 
                            newFolder.getName().equals(oldFolder.getName()) &&
                                    !newFolder.getItemCount().equals(oldFolder.getItemCount())
                    )).forEach(folder -> {
                        //dostuff
    });