4 回答
TA贡献1777条经验 获得超3个赞
你可以这样尝试:
Map<TimeStamp, Optional<Obj>> result =
list.stream().collect(Collectors.groupingBy(
Obj::getTs,
Collectors.maxBy(Comparator.comparing(Obj::getGenerationTs))
));
正如@Naman 在评论中所说的更完整的选项:
list.stream().collect(Collectors.groupingBy(
Obj::getTs,
Collectors.maxBy(Comparator.comparing(Obj::getGenerationTs))
)).values().stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
TA贡献1810条经验 获得超5个赞
您当然可以Stream使用地图收集器然后获取值来做到这一点
Collection<Obj> objects = list.stream()
.collect(Collectors.toMap(Obj::getTimeStamp,
Function.identity(),
(o1, o2) -> o1.getGenerationTs().isBefore(o2.getGenerationTs()) ? o2 : o1))
.values();
List<Obj> listOfObjects = new ArrayList<>(objects);
甚至更短:
List<Obj> result = list.stream()
.collect(Collectors.collectingAndThen(
Collectors.toMap(Obj::getTimeStamp,
Function.identity(),
(o1, o2) -> o1.getGenerationTs().isBefore(o2.getGenerationTs()) ? o2 : o1),
m -> new ArrayList<>(m.values())));
TA贡献1876条经验 获得超6个赞
如果您已经有一个排序列表(按 降序generationTs),就像您在示例代码中那样,您可以使用 aHashSet和Collection.removeIf()从该列表中删除所有重复的时间戳:
list.sort(Comparator.comparing(Obj::getTs)
.thenComparing(Comparator.comparing(Obj::getGenerationTs)
.reversed()));
Set<Timestamp> keys = new HashSet<>();
list.removeIf(o -> !keys.add(o.getTs()));
使用此解决方案,您不必创建新列表,只需修改您拥有的列表。该集合将您要维护的所有密钥存储在列表中。因为列表已排序,所以最新的对象保留在列表中,而其他值则被删除。
您共享的数据的结果将是:
Obj[ts=2019-05-02T09:00:00Z, generationTs=2019-05-02T21:00:00Z, value=1]
Obj[ts=2019-05-02T09:30:00Z, generationTs=2019-05-02T22:00:00Z, value=5]
Obj[ts=2019-05-02T10:00:00Z, generationTs=2019-05-02T22:00:00Z, value=6]
Obj[ts=2019-05-02T10:30:00Z, generationTs=2019-05-02T21:00:00Z, value=4]
如果您已经有一个排序列表,则此解决方案应该是最快的解决方案之一。
TA贡献1725条经验 获得超7个赞
下面是一种方法。
将第一个时间戳分组,然后使用 maxBy 查找具有最新一代时间戳的对象。最后对第一个时间戳进行排序并打印出来。
maxBy 将产生 Optional 的事实有点难看,但我找不到避免它的方法。
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.maxBy;
import java.time.Instant;
import java.util.Optional;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
public class SortTest {
@Test
public void t() {
final Stream<Obj> s = Stream.of(new Obj("2019-05-02T09:00:00Z", "2019-05-02T21:00:00Z", 1),
new Obj("2019-05-02T09:30:00Z", "2019-05-02T21:00:00Z", 2),
new Obj("2019-05-02T10:00:00Z", "2019-05-02T21:00:00Z", 3),
new Obj("2019-05-02T10:30:00Z", "2019-05-02T21:00:00Z", 4),
new Obj("2019-05-02T09:30:00Z", "2019-05-02T22:00:00Z", 5),
new Obj("2019-05-02T10:00:00Z", "2019-05-02T22:00:00Z", 6));
s.collect(groupingBy(o -> o.ts, maxBy((o1, o2) -> o1.generationTs.compareTo(o2.generationTs))))
.values()
.stream()
.map(Optional::get)
.sorted((o1, o2) -> o1.ts.compareTo(o2.ts))
.forEach(System.out::println);
}
private class Obj {
Instant ts;
Instant generationTs;
int i;
Obj(final String ts, final String generationTs, final int i) {
this.ts = Instant.parse(ts);
this.generationTs = Instant.parse(generationTs);
this.i = i;
}
@Override
public String toString() {
return String.format("%s %s %d", ts, generationTs, i);
}
}
}
添加回答
举报