Проблема сортировки потоков - PullRequest
0 голосов
/ 13 февраля 2019

У меня есть список элементов (объект MyDetail), которые я хочу отсортировать с помощью методов потоковой сортировки.Объект имеет 3 поля: field1, field2, field3.Я хочу отсортировать сначала по field3, затем по field2, затем по field1, все в обратном порядке.Поэтому я написал метод sortMyList.

У меня есть список несортированных элементов unSortedDetails: myDetail1: «20180201», false, false myDetail2: «20180101», false, false myDetail3: «20180101», false, true

после sortMyList (unSortedDetails) я ожидаю, что мой результат будет myDetail3, myDetail1, myDetail2, но фактический результат - myDetail1, myDetail3, myDetail2, Why?

, поэтому, если я реализую Comparable для MyDetail, как показано ниже, тоэто работает как ожидалось.это так странноЯ не мог понять, почему.спасибо за любую помощь!

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;
}
                }

1 Ответ

0 голосов
/ 13 февраля 2019

Есть несколько проблем с вашим компаратором.Во-первых, каждый раз, когда вы звоните 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

, но ваш компаратор сначала проверяет field1, затем field2, затем field3 (поскольку вв том порядке, в котором вы добавили их через .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.


Кстати, как указал с помощью Хольгер Вы можете достичь того же эффекта с помощью

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

Обратите внимание, что Comparaor.comparing(FunctionToValue) и thenComparing(FunctionToValue) создаст ASCending Компараторы для выбранного значения.

Итак, первые 3 строки создают компаратор, описывающий порядок F3 ASC, F2 ASC, F1 ASC.После его изменения
~(F3 ASC, F2 ASC, F1 ASC) также дает нам желаемое F3 DESC, F2 DESC, F1 DESC.

...