在这种情况下如何对列表进行流式排序?

我在 Java 中有一个带有两个时间戳的对象列表,例如:


Obj(TimeStamp ts,TimeStamp generationTs,int 值)。


最后,我不希望列表中的两个项目具有相同的 ts。如果有的话,我只想保留最新一代 T 的那个。


实际上,我有那个代码,它可以工作,但我想知道如果使用流,我不能做更好的事情吗?


list.sort(Collections.reverseOrder());

List<Obj> returnedList = Lists.newArrayList();

if (!list.isEmpty()) {

   returnedList.add(list.get(0));

   Iterator<Obj> i = list.iterator();

   while (i.hasNext()) {

       Obj lastObj = returnedList.get(returnedList.size() - 1);

       Obj nextObj = i.next();

       if (!lastObj.getTs().isEqual(nextObj.getTs())) {

           returnedList.add(nextObj);

       } else {

           if (lastObj.getGenerationTs().isBefore(nextObj.getGenerationTs())) {

             returnedList.remove(lastObj);

             returnedList.add(nextObj);

           }

        }

    }

}

如果列表是:


{("2019-05-02T09:00:00Z", "2019-05-02T21:00:00Z", 1),

("2019-05-02T09:30:00Z", "2019-05-02T21:00:00Z", 2),

("2019-05-02T10:00:00Z", "2019-05-02T21:00:00Z", 3),

("2019-05-02T10:30:00Z", "2019-05-02T21:00:00Z", 4),

("2019-05-02T09:30:00Z", "2019-05-02T22:00:00Z", 5),

("2019-05-02T10:00:00Z", "2019-05-02T22:00:00Z", 6) }

它必须返回:


{("2019-05-02T09:00:00Z", "2019-05-02T21:00:00Z", 1),

("2019-05-02T09:30:00Z", "2019-05-02T22:00:00Z", 5),

("2019-05-02T10:00:00Z", "2019-05-02T22:00:00Z", 6) 

("2019-05-02T10:30:00Z", "2019-05-02T21:00:00Z", 4) }


交互式爱情
浏览 110回答 4
4回答

慕森王

你可以这样尝试:Map<TimeStamp, Optional<Obj>> result =&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list.stream().collect(Collectors.groupingBy(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Obj::getTs,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Collectors.maxBy(Comparator.comparing(Obj::getGenerationTs))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;));正如@Naman 在评论中所说的更完整的选项:list.stream().collect(Collectors.groupingBy(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Obj::getTs,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Collectors.maxBy(Comparator.comparing(Obj::getGenerationTs))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; )).values().stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .filter(Optional::isPresent)&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(Optional::get)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());

森栏

您当然可以Stream使用地图收集器然后获取值来做到这一点Collection<Obj> objects = list.stream()&nbsp; &nbsp; .collect(Collectors.toMap(Obj::getTimeStamp,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Function.identity(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (o1, o2) -> o1.getGenerationTs().isBefore(o2.getGenerationTs()) ? o2 : o1))&nbsp; &nbsp; .values();List<Obj> listOfObjects = new ArrayList<>(objects);甚至更短:List<Obj> result = list.stream()&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.collectingAndThen(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Collectors.toMap(Obj::getTimeStamp,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Function.identity(),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (o1, o2) -> o1.getGenerationTs().isBefore(o2.getGenerationTs()) ? o2 : o1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; m -> new ArrayList<>(m.values())));

HUX布斯

如果您已经有一个排序列表(按 降序generationTs),就像您在示例代码中那样,您可以使用 aHashSet和Collection.removeIf()从该列表中删除所有重复的时间戳:list.sort(Comparator.comparing(Obj::getTs)&nbsp; &nbsp; &nbsp; &nbsp; .thenComparing(Comparator.comparing(Obj::getGenerationTs)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .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]如果您已经有一个排序列表,则此解决方案应该是最快的解决方案之一。

qq_遁去的一_1

下面是一种方法。将第一个时间戳分组,然后使用 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 {@Testpublic void t() {&nbsp; &nbsp; final Stream<Obj> s = Stream.of(new Obj("2019-05-02T09:00:00Z", "2019-05-02T21:00:00Z", 1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Obj("2019-05-02T09:30:00Z", "2019-05-02T21:00:00Z", 2),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Obj("2019-05-02T10:00:00Z", "2019-05-02T21:00:00Z", 3),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Obj("2019-05-02T10:30:00Z", "2019-05-02T21:00:00Z", 4),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Obj("2019-05-02T09:30:00Z", "2019-05-02T22:00:00Z", 5),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; new Obj("2019-05-02T10:00:00Z", "2019-05-02T22:00:00Z", 6));&nbsp; &nbsp; s.collect(groupingBy(o -> o.ts, maxBy((o1, o2) -> o1.generationTs.compareTo(o2.generationTs))))&nbsp; &nbsp; .values()&nbsp; &nbsp; .stream()&nbsp; &nbsp; .map(Optional::get)&nbsp; &nbsp; .sorted((o1, o2) -> o1.ts.compareTo(o2.ts))&nbsp; &nbsp; .forEach(System.out::println);}private class Obj {&nbsp; &nbsp; Instant ts;&nbsp; &nbsp; Instant generationTs;&nbsp; &nbsp; int i;&nbsp; &nbsp; Obj(final String ts, final String generationTs, final int i) {&nbsp; &nbsp; &nbsp; &nbsp; this.ts = Instant.parse(ts);&nbsp; &nbsp; &nbsp; &nbsp; this.generationTs = Instant.parse(generationTs);&nbsp; &nbsp; &nbsp; &nbsp; this.i = i;&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public String toString() {&nbsp; &nbsp; &nbsp; &nbsp; return String.format("%s %s %d", ts, generationTs, i);&nbsp; &nbsp; }}}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java