假设您有一个用户列表,该列表实际上来自数据库存储库。
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、名称和可用于访问第三方服务的 key 。
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());
问题 - 从列表中查找医疗记录需要两次:一次在 filter
中,然后在 map
中。您可以缩短过滤器以使用诸如 anyMatch
之类的内容,但我并不想减少此处的行数。我正在寻找一种将医疗记录(如果存在)和用户一次性传递给 generateReport(user, MedicalRecord)
的方法。理论上,它可能允许 map 采用两个值,例如map((用户,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);
}
最佳答案
In theory it might be something that allows map to take two values e.g. map((user, medicalRecord) -> generateReport(user, medicalRecord))
我们可以使用Map.Entry
来做到这一点,它可以由 Map.entry(key, value)
构造,或使用组件 User
和 MedicalRecord
创建记录类。
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 - 在 Java Stream 中组合过滤器和映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76395609/