3 回答
TA贡献1877条经验 获得超6个赞
我建议你从一个Comparator<Person>优先考虑最大值 score然后是最小值的自定义开始optionalId。为简洁起见,这是将其传递给变量的好方法:
final Comparator<Person> comparator = Comparator
.comparing(Person::getScore) // descending score first
.thenComparing(Comparator // then ..
.comparing(Person::getOptionalId) // .. optionalId
.reversed()); // .. but ascending
现在使用一些收集器java流.
Collectors::groupingBy按值和下游对所有Persons进行分组id
Collectors::reducing将所有Person相同的 s减少id为一个,使用Comparator<Person>得到最高score和最低的一个optionalId。
Collectors::collectingAndThenCollection<Optional<Person>>将结构从to展平,Collection<Person>因为任何减少操作都会导致Optional- 此步骤是可选的,可能会根据您的示例跳过。
这是代码:
Collection<Person> filtered = records.stream() // Stream<Person>
.collect(Collectors.groupingBy( // from Map<Long, List<Person>>
Person::getId,
Collectors.collectingAndThen( // .. downstream to ..
Collectors.reducing((a, b) -> // .. Map<Long, Optional<Person>>
comparator.compare(a, b) > 0 ? a : b),
Optional::get)) // .. Map<Long, Person>
.values(); // .. Collection<Person>
[人 [id=1, score=90, optionalId=2], 人 [id=2, score=100, optionalId=3]]
TA贡献1824条经验 获得超8个赞
对于给定的 Id 值,必须有一个 Person。Id 值的存在完全取决于 Person。因此,如果存在 Id,则也必须存在 Person。因此,将 aOptional<Person>作为地图的值有什么意义。相比之下,仅将一个Person实例作为map. 在这里,我将toMap收集器与 一起使用BinaryOperator.maxBy来完成工作。这是它的外观。请注意如何将BinaryOperator.maxBy用作mergeFunction。
Map<Integer, Person> maxPersonById = records.stream()
.collect(Collectors.toMap(Person::getId, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Person::getScore)
.thenComparing(Comparator.comparing(Person::getOptionalId).reversed()))));
这是上述给定输入的输出。
{1=Person [id=1, score=90, optionalId=2], 2=Person [id=2, score=100, optionalId=3]}
TA贡献1772条经验 获得超5个赞
您可以尝试使用以下聚合的流代码ID,然后使用两级排序找到最大分数,首先是分数,然后是可选的 ID,以防分数平局:
import static java.util.Collections.reverseOrder;
import static java.util.Comparator.comparing;
Map<Long, Optional<Person>> result1 = records.stream()
.collect(Collectors.groupingBy(Person::getId,
Collectors.maxBy(
Comparator.comparing(Person::getScore)
.thenComparing(reverseOrder(comparing(Person::getOptionalId))))));
Optional[ID: 1 Score: 90 OptionalId: 2]
Optional[ID: 2 Score: 100 OptionalId: 3]
这里的技巧是仅反转可选 ID 的排序顺序,我们希望它是升序的,而不是降序的。默认情况下排序顺序为降序,因为我们正在调用Collections.maxBy.
添加回答
举报