簡體   English   中英

流分類問題

[英]Stream sorting issue

我有要使用流排序方法排序的項目列表(MyDetail對象)。 該對象具有3個字段:field1,field2,field3。 我想先按field3排序,然后按field2再按field1排序,所有順序都相反。 所以我寫了一個方法sortMyList。

我有未排序項目unSortedDetails的列表,如下所示:myDetail1:“ 20180201”,錯誤,錯誤myDetail2:“ 20180101”,錯誤,錯誤myDetail3:“ 20180101”,錯誤,true

在sortMyList(unSortedDetails)之后,我希望我的結果是myDetail3,myDetail1,myDetail2,但實際結果是myDetail1,myDetail3,myDetail2,為什么?

因此,如果我像下面那樣為MyDetail實現Comparable,那么它將按預期工作。 這太奇怪了。 我不知道為什么。 謝謝你的幫助!

public List<MyDetail> sortMyList(List<MyDetail> unSortedDetails){
    List<MyDetail> myDetails = unSortedDetails
                        .stream().sorted(Comparator.comparing(MyDetail::getField11).reversed()
                                .thenComparing(MyDetail::getField2).reversed()
                                .thenComparing(MyDetail::getField3).reversed())
                        .collect(Collectors.toList());
                        return myDetails;
                        }

                        @Setter
                        @Getter
                        public class MyDetail{
                            String field1;
                            Boolean field2; 
                            Boolean field3; 
                        }



                @Setter
                @Getter
                public class MyDetail implement Comparable<MyDetail>{
                    String field1;
                    Boolean field2; 
                    Boolean field3; 

                        @Override
                        public int compareTo(MyDetail o) {
                            if (this == o || this.equals(o)) return 0;
                            if (field3) return -1;
                            if (o.field3) return 1;
                            if (!field3 && !o.field3 && field2) return -1;
                            if(!field3 && !o.field3 &&!field2 && o.field2) return 1;
                            if(!field3 && !o.field3
                                    &&!field2 && !o.field2){
                                return o.field1.compareTo(field1);
                            }
                            return 0;
}
                }

比較器幾乎沒有問題。 首先,每次調用reversed()都會反轉比較器的所有先前設置。

因此,您的比較器表示(請參閱注釋中的步驟, FieldX減少為Fx

Comparator.comparing(MyDetail::getField11)     //  F1 ASC
          .reversed()                          //~(F1 ASC) 
                                               //  F1 DESC 
          .thenComparing(MyDetail::getField2)  //  F1 DESC, F2 ASC  
          .reversed()                          //~(F1 DESC, F2 ASC) 
                                               //  F1 ASC,  F2 DESC
          .thenComparing(MyDetail::getField3)  //  F1 ASC,  F2 DESC, F3 ASC
          .reversed()                          //~(F1 ASC,  F2 DESC, F3 ASC)
                                               //  F1 DESC, F2 ASC,  F3 DESC

因此您最終獲得了Field1 DESC, Field2 ASC, Field3 DESC訂單。

要為每個字段指定反向順序,請通過傳遞該字段的已反向比較器,例如.thenComparing(Comparator.comparing(YourClass::getField).reversed())


下一個問題是比較器使用的字段順序。 在您的問題中,您說:

我想先按field3然后按field2然后按field1排序

但是您的比較器首先檢查field1,然后檢查field2,然后檢查field3(因為.thenComparing順序,您通過.thenComparing添加了它們)。

您的代碼應該更像

Comparator.comparing(MyDetail::getField13).reversed()
          .thenComparing(Comparator.comparing(MyDetail::getField2).reversed())
          .thenComparing(Comparator.comparing(MyDetail::getField1).reversed())

因此,您正在創建~(F3 ASC), ~(F2 ASC), ~(F1 ASC) ,這將導致F3 DESC, F2 DESC, F1 DESC


Holger 指出的BTW可以達到相同的效果

Comparator.comparing(MyDetail::getField3)
          .thenComparing(MyDetail::getField2) 
          .thenComparing(MyDetail::getField1)
          .reversed()

請注意, Comparaor.comparing(FunctionToValue)thenComparing(FunctionToValue)將為選定的值創建ASCending比較器。

因此F3 ASC, F2 ASC, F1 ASC行構造了比較器,描述了順序F3 ASC, F2 ASC, F1 ASC 反轉后
~(F3 ASC, F2 ASC, F1 ASC)也給出了我們所需的F3 DESC, F2 DESC, F1 DESC

暫無
暫無

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

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