簡體   English   中英

分組后流不保留順序

[英]Stream doesn't preserve the order after grouping

我有一個List名稱availableSeats我正在通過blockIndex屬性進行排序和分組,如下所示:

availableSeats.stream()
                .sorted(Comparator.comparing(SeatedTicketAssignment::getBlockIndex))
                .collect(Collectors.groupingBy(SeatedTicketAssignment::getBlockIndex))
                .forEach((block, blockAssignments) -> {
                     //Rest of the code
                } 

問題是分組的結果不是由blockIndex排序的。

請記住, Collectors#groupingBy(Function)將返回一個HashMap ,它不保證順序。 如果您希望排序符合聚合標識(您的i % 2 == 0結果)顯示的順序,那么您可以使用LinkedHashMap

.collect(Collectors.groupingBy(i -> i % 2 == 0, LinkedHashMap::new, Collectors.toList()))

將返回LinkedHashMap<Boolean, List<SeatedTicketAssignment>> (因為您的收集器按布爾值分組)。 此外,由於收集器使用的列表是ArrayList ,因此它應該保留流相對於列表的迭代順序。

不幸的是,Stream API實現並不知道您傳遞的流已按您所需的順序排序,因此“分組”實際上是微不足道的。 因此,它使用默認方式,它基本上類似於這個SO答案,即為組創建一個Map並用流的元素填充它。 默認情況下,使用的Map實現是HashMap(請參閱此處的代碼 ),這有助於提高性能但對目標不利,因為HashMap不會保留鍵的順序而不是第一次排序。

可能看起來有些不吉利的是Group By僅在Stream API中作為“收集器”實現,因此您不能先進行分組,然后進行單行排序。 但這似乎是有意的:沒有完全實現結果就沒有辦法實現Group By,所以它不能是懶惰的,因此必須是一個收集器。 @Rogue為LinkedHashMap提供了一個很好的技巧,但對我來說它是綁定到實現細節。 我仍然會寫幾行代碼和第一組,然后按鍵對列表的條目(即實際分組的HashMap)進行排序。 最有可能的是它會更快。

由於groupingBy收集器不需要排序輸入,因此您可以在收集后對組進行排序。 這將比首先對項目排序更快,無論如何,假設組中的項目少於項目:

availableSeats.stream()
        .collect(Collectors.groupingBy(SeatedTicketAssignment::getBlockIndex))
        .entrySet().stream()
        .sorted(Comparator.comparing(Map.Entry::getKey))
        .forEach(mapEntry -> {
             //Rest of the code
        } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM