使用 Java 流有条件地内联修改集合
Conditionally modifying collections inline using Java Streams
Java 11 在这里。我有 2 个 List<Fizzbuzz>
个实例,latest
和 current
。 “最新”列表是最新 热门话题列表。 “当前”列表是我数据库中的 Fizbuzze 列表。我正在比较这些列表。
我需要比较这些列表并创建第三个列表,additions
,其中包含 latest
列表中未在 current
列表中找到的任何 Fizzbuzze。它是数据库中没有记录的“新”Fizzbuzze 列表。
此外,我需要将每个添加的 processedAt
字段 (Instant
) 设置为相同的当前 date/time。我想尝试使用 Java 流 API 内联完成这一切。我可以用“老式”的方式完成这个:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
List<Fizzbuzz> additions = new ArrayList<>();
Instant now = Instant.now();
for (Fizzbuzz latest : latestList) {
if (!currentList.contains(latest)) {
latest.setProcessedAt(now);
additions.add(latest);
}
}
我使用 Java 流 API 的最佳尝试是:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
Instant now = Instant.now();
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.forEach(addition -> {
addition.setProcessedAt(now);
})
.collect(Collectors.toList());
这会产生一个编译器错误,因为 forEach
没有 return 任何东西。谁能发现我哪里出错了?
您可以使用 Stream.peek
,它允许对每个元素应用一个操作并且不保留结果(如果有的话)并恢复流
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.peek(addition -> addition.setProcessedAt(now))
.collect(Collectors.toList());
要应用将数据转换为其他内容的修改操作,您需要 Stream.map
您需要创建 Instant 作为最终变量才能在 lamda 表达式中使用它
一个集合操作和List.forEach()
流不应该有副作用。因此,您不应在流操作中修改任何流元素。所以我建议你完全不要为你的两个需求使用流。
List<Fizzbuzz> additions = new ArrayList<>(latestList);
additions.removeAll(currentList);
Instant now = Instant.now();
additions.forEach(addition -> addition.setProcessedAt(now));
前两行查找 latestList
中不在 currentList
中的 fizzbuzzes。 removeAll
方法被称为 集合操作 ,不是因为它适用于集合,而是因为它用于查找类似 集合差异的东西 在两个集合之间(在本例中是两个列表)。 (其他集合操作是 addAll()
用于并集,retainAll()
用于交集。)
然后最后两行根据需要设置processedAt
。
Java 11 在这里。我有 2 个 List<Fizzbuzz>
个实例,latest
和 current
。 “最新”列表是最新 热门话题列表。 “当前”列表是我数据库中的 Fizbuzze 列表。我正在比较这些列表。
我需要比较这些列表并创建第三个列表,additions
,其中包含 latest
列表中未在 current
列表中找到的任何 Fizzbuzze。它是数据库中没有记录的“新”Fizzbuzze 列表。
此外,我需要将每个添加的 processedAt
字段 (Instant
) 设置为相同的当前 date/time。我想尝试使用 Java 流 API 内联完成这一切。我可以用“老式”的方式完成这个:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
List<Fizzbuzz> additions = new ArrayList<>();
Instant now = Instant.now();
for (Fizzbuzz latest : latestList) {
if (!currentList.contains(latest)) {
latest.setProcessedAt(now);
additions.add(latest);
}
}
我使用 Java 流 API 的最佳尝试是:
List<Fizzbuzz> latestList = getFromFile();
List<Fizzbuzz> currentList = getFromDatabase();
Instant now = Instant.now();
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.forEach(addition -> {
addition.setProcessedAt(now);
})
.collect(Collectors.toList());
这会产生一个编译器错误,因为 forEach
没有 return 任何东西。谁能发现我哪里出错了?
您可以使用 Stream.peek
,它允许对每个元素应用一个操作并且不保留结果(如果有的话)并恢复流
List<Fizzbuzz> additions = latestList.stream()
.filter(latest -> !currentList.contains(latest))
.peek(addition -> addition.setProcessedAt(now))
.collect(Collectors.toList());
要应用将数据转换为其他内容的修改操作,您需要 Stream.map
您需要创建 Instant 作为最终变量才能在 lamda 表达式中使用它
一个集合操作和List.forEach()
流不应该有副作用。因此,您不应在流操作中修改任何流元素。所以我建议你完全不要为你的两个需求使用流。
List<Fizzbuzz> additions = new ArrayList<>(latestList);
additions.removeAll(currentList);
Instant now = Instant.now();
additions.forEach(addition -> addition.setProcessedAt(now));
前两行查找 latestList
中不在 currentList
中的 fizzbuzzes。 removeAll
方法被称为 集合操作 ,不是因为它适用于集合,而是因为它用于查找类似 集合差异的东西 在两个集合之间(在本例中是两个列表)。 (其他集合操作是 addAll()
用于并集,retainAll()
用于交集。)
然后最后两行根据需要设置processedAt
。