假设您有一个用户列表,实际上该列表来自数据库存储库.

User alice = new User(1, "alice", "9akDj18xA");
User bob = new User(2, "bob", "mLih41nZxx");
User carol = new User(3, "carol", "tFxn2Ad70");

List<User> users = List.of(alice, bob, carol);

每个用户都有一个ID、一个名称和一个可用于访问第三方服务的密钥.

class User {
    int id;
    String name;
    String consentKey;

    public User(int id, String name, String consentKey) {
      this.id = id;
      this.name = name;
      this.consentKey = consentKey;
    }
  }

有时,第三方服务返回的数据--医疗记录--看起来是这样的.

class MedicalRecord {
    int userId;
    String information;

    public MedicalRecord(int userId, String information) {
      this.userId = userId;
      this.information = information;
    }
  }

但在其他情况下,当键无效时,它会返回NULL,因此我们会将其过滤掉.

// Calls a third party service that returns data for some users only
List<MedicalRecord> medicalRecords =
    users.stream()
        .map(user -> Optional.ofNullable(fetchMedicalRecord(user)))
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());

该任务是生成将用户数据与医疗记录相结合的报告,但仅在医疗记录存在的情况下.以下是我为实现此目的而编写的代码.

return users.stream()
    .filter(
        user -> {
          Optional<MedicalRecord> medicalRecord =
              medicalRecords.stream()
                  .filter(record -> record.userId == user.id)
                  .findFirst();
          return medicalRecord.isPresent();
        })
    .map(
        user -> {
          MedicalRecord medicalRecord =
              medicalRecords.stream()
                  .filter(record -> record.userId == user.id)
                  .findFirst()
                  .get();

          // Both user and medical record are needed here
          return generateReport(user, medicalRecord);
        })
    .collect(Collectors.toList());

The problem-从列表中查找病历需要两次:一次是每filter次,另一次是每map次.您可以将筛选器缩短为使用类似anyMatch的内容,但我并不是要减少这里的行数.我正在寻找的是一种方法,既传递医疗记录(如果存在)和用户一口气到generateReport(user, medicalRecord).从理论上讲,它可能是允许MAP接受两个值的东西,例如map((user, medicalRecord) -> generateReport(user, medicalRecord)).

请注意,这是一个简化的示例,我只是为了说明一个问题而编造的,所以忽略过滤器/映射范围之外的小问题.


如果您想要一个完整的工作示例,下面是运行这一切所需的两个函数.

  private static MedicalRecord fetchMedicalRecord(User user) {
    if (!user.consentKey.equals("tFxn2Ad70")) {
      String information = String.format("%s's medical record", user.name);
      return new MedicalRecord(user.id, information);
    } else {
      return null;
    }
  }

  private String generateReport(User user, MedicalRecord medicalRecord) {
    return String.format("%s's report - %s", user.name, medicalRecord.information);
  }

推荐答案

从理论上讲,它可能允许map接受两个值,例如map((User,MedicalRecord)->;GenerateReport(User,MedicalRecord))

我们可以使用Map.Entry来实现这一点,它可以由Map.entry(key, value)构造,也可以使用组件UserMedicalRecord创建一个Record类.

        users.stream()
                .map(user -> Map.entry(user, Optional.ofNullable(fetchMedicalRecord(user))))
                .filter(e -> e.getValue().isPresent())
                .map(e -> generateReport(e.getKey(), e.getValue().get()))
                .toList();

参考资料:

Java - How to create new Entry (key, value)

Java相关问答推荐

日食IDE 2024-03在Ubuntu下崩溃,导致hr_err_pid.log

neo4j java驱动程序是否会在错误发生时自动回滚事务?

为什么Java的代码工作(if condition内部的实例)

查找剩余的枚举

具有阻塞方法的开源库是否应该为执行提供异步选项?

把一条整型短裤和两条短裤装成一条长的

MySQL数据库中未应用具有Spring数据的唯一约束

Java SSLKeyManager出厂密码

Java页面筛选器问题

如何在Spring Boot中创建可以将值传递给配置的&Enable&Quot;注释?

舰队运行配置Maven版本

无法使用Freemarker从XML中读取重复的标记值

我可以在@Cacheable中使用枚举吗

Spring Validator批注不起作用

没有Tomcat,IntelliJ如何在本地运行API?

当使用不同的参数类型调用时,为什么围绕Objects.equals的类型安全包装不会失败?

为什么我得到默认方法的值而不是被覆盖的方法的值?

message.acknowledge()没有';在使用Spring Boot在ActiveMQ中读取消息后,t将消息出列

SonarQube在合并升级到java17后对旧代码提出错误

Spring Integration SFTP 连接失败 - 无法协商 kex 算法的密钥交换