В чем разница между методом сортировки интерфейса списка и методом сортировки интерфейса потока? - PullRequest
2 голосов
/ 05 мая 2019

Я заинтересован в сортировке списка объектов на основе атрибута даты в этом объекте.Я могу использовать метод сортировки списка.

list.sort( (a, b) -> a.getDate().compareTo(b.getDate()) );

Или я могу использовать метод сортировки потоков

List<E> l = list.stream()
                .sorted( (a, b) -> a.getDate().compareTo(b.getDate()))
                .collect(Collectors.toList());

Из обоих вышеупомянутых вариантов, которые мы должны использовать и почему?

Я знаю, что предыдущий обновит мой исходный список, а позже он не обновит исходный список, а вместо этого даст мне новый новый объект списка.

Итак, мне все равно, обновляется мой первоначальный список или нет.Итак, какой вариант является хорошим и почему?

Ответы [ 5 ]

2 голосов
/ 05 мая 2019

Если вам нужно только отсортировать List, и не нужны никакие другие потоковые операции (такие как фильтрация, отображение и т. Д.), Нет смысла добавлять накладные расходы на создание Stream изатем создать новый List.Было бы эффективнее просто отсортировать оригинал List.

1 голос
/ 05 мая 2019

Если вы хотите знать, какой из них лучший, лучше всего сравнить его: вы можете повторно использовать мой ответ JMH тест .

Следует отметить, что:

  • List::sort используйте Arrays::sort. Это создает массив перед сортировкой. Он не существует для других Collection.
  • Stream::sorted выполняется как состояние полной промежуточной операции. Это означает, что Stream нужно запомнить его состояние.

Без тестирования я бы сказал, что:

  • Вы должны использовать collection.sort(). Легче читать: collection.stream().sorted().collect(toList()) - это способ долго читать, и если вы не отформатируете свой код хорошо, у вас может возникнуть головная боль (я преувеличиваю), прежде чем понять, что эта строка просто сортирует.
  • sort() на Stream следует называть:
    • , если вы фильтруете много элементов, делая Stream по размеру меньше, чем коллекция ( сортирует N элементов, затем фильтрует N элементов не то же самое, что фильтрует N элементов, а затем сортирует K элементов с K <= N </em>).
    • если у вас есть преобразование карты после сортировки, и вы теряете способ сортировки с использованием оригинального ключа.

Если вы используете ваш поток с другой промежуточной операцией, тогда sort может потребоваться / полезно:

collection.stream()    // Stream<U> #0
          .filter(...) // Stream<U> #1
          .sorted()      // Stream<U> #2
          .map(...)    // Stream<V> #3
          .collect(toList()) // List<V> sorted by U.
          ;

В этом примере фильтр применяется перед сортировкой: поток # 1 меньше, чем # 0, поэтому стоимость сортировки с потоком может быть меньше, чем Collections.sort ().

Если все, что вы делаете - это просто фильтрация, вы также можете использовать операцию TreeSet или collectingAndThen:

collection.stream()    // Stream<U> #0
          .filter(...) // Stream<U> #1
          .collect(toCollection(TreeSet::new))
          ;

Или:

collection.stream() // Stream<U>
          .filter(...) // Stream<U>
          .collect(collectingAndThen(toList(), list -> {
            list.sort(); 
            return list;
          })); // List<V>
1 голос
/ 05 мая 2019

Потоки имеют некоторые накладные расходы, потому что он создает много новых объектов, таких как бетон Stream, Collector и новый List.Поэтому, если вы просто хотите отсортировать список и не беспокоиться о том, будет ли изменен оригинал, используйте List.sort.

Существует также Collections.sort, который является более старым API.Разницу между ним и List.sort можно найти здесь .

Stream.sorted полезно, когда вы выполняете другие потоковые операции наряду с сортировкой.

Ваш код также можетпереписать с Comparator:

list.sort(Comparator.comparing(YourClass::getDate)));
0 голосов
/ 05 мая 2019

Вы используете первый метод

list.sort((a, b) -> a.getDate().compareTo(b.getDate()));

, он намного быстрее второго и не создает новый промежуточный объект.Вы можете использовать второй метод, когда хотите выполнить некоторые дополнительные потоковые операции (например, фильтрация, отображение).

0 голосов
/ 05 мая 2019

Первый будет лучше с точки зрения производительности. В первом метод сортировки просто сравнивает элементы списка и упорядочивает их. Второй создаст поток из вашего списка, отсортирует его и создаст новый список из этого потока.

В вашем случае, поскольку вы можете обновить первый список, первый подход лучше, как с точки зрения производительности, так и потребления памяти. Второй вариант удобен, если вам нужно и с потоком, или если у вас есть поток и вы хотите получить отсортированный список.

...