首页 > 解决方案 > 试图将嵌套的 for 循环表示为 Java 流,但感到困惑

问题描述

我试图更好地理解 Java 中的流,而我只是试图将嵌套的 for 循环表示为流,但我很难弄清楚。

我尝试了一些东西,但我似乎无法掌握它。

例如,像这样的东西。

for (Profile profile : profiles) {
    for (User user : users) {
        if (user.getUserId().equals(profile.getProfileId())) {
           profile.setField(false);
        }
    }
}

在 Java 中如何将其作为流来执行?

标签: javajava-stream

解决方案


我认为您正在尝试理解流,但让我说for版本并没有更差,Stream版本也没有更好:性能测试和直觉可能会帮助您,以及可读性。

也就是说,您的问题是您的第二个外观需要第一个工作:

profiles.stream()
        .filter(profile -> users.stream() 
                                .anyMatch(user -> user.getUserId().equals(profile.getProfileId())))
        .forEach(profile -> profile.setField(false));
  

这与您的 for 循环严格不同:您setField在每个配置文件中调用多次,而在流版本中,只有当有一个匹配的用户时才会执行此操作。我假设它setField是一个 setter,因此,由于它的值是恒定的,所以它被调用一次还是多次都无关紧要。

在这种情况下,我建议您不要使用第一个流,或者将自己限制为forEach

profiles.forEach(profile -> profile.setField(!users.stream() 
                                   .anyMatch(user -> user.getUserId().equals(profile.getProfileId())));

这可以通过首先获取所有用户 ID 并使用生成集中的包含来简化:

   var userIds = users.stream().map(User::getUserId).collect(toSet());
   profiles.forEach(profile -> profile.setField(!userIds.contains(profile.getProfileId()));

推荐阅读