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條經驗 獲得超8個贊
下面是一種方法。
將第一個時間戳分組,然后使用 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);
}
}
}
添加回答
舉報
