Достаточно ли умен фильтр потока Java, чтобы игнорировать ненужные элементы в упорядоченном потоке?

Допустим, у меня есть следующее:

List<Integer> orderedList = Stream.of(5, 4, 0, 2, 1).sorted().toList();

Если я применю фильтр, например

List<Integer> filteredList = orderedList.stream().filter(integer -> integer < 3).toList();

Будет ли filter проверять все элементы в orderedList, или, учитывая, что он упорядочен, фильтрация прекратится после достижения первого ложного условия, т. е. integer >= 3, или он всегда проверяет все элементы?

Если он проверяет все элементы, есть ли более разумный способ фильтровать элементы в ситуации с упорядоченным списком?

вот почему takeWhile()

user85421 30.08.2024 17:15
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В вашем сценарии, поскольку вы возвращаете список со всеми элементами, соответствующими фильтру, filter() применяется ко всем элементам в потоке.

Если вы хотите остановить обработку, когда определенное условие истинно/ложно, вы можете использовать takeWhile() из Java 9:

orderedList.stream().takeWhile(v -> v < 3).forEach(System.out::println);

Возможно, обратите внимание, что takeWhile был добавлен в Java 9, поскольку, похоже, многие люди все еще используют Java 8.

greg-449 30.08.2024 14:56

"Is there a smarter way to filter items in a situation with an ordered list?"

Это зависит от того, что вы подразумеваете под умнее. Вы можете просто использовать императивное решение с циклом и не использовать потоки. Или, если ваш упорядоченный список не является неизменяемым, вы можете сделать следующее:

list.removeIf(i->i >= 3);

Если целью является эффективность, обратите внимание, что нет никакой гарантии, что постобработка отсортированного списка будет более эффективной, поскольку сначала сортируется список O(nLogn), а затем, возможно, O(n) проверяется для фильтрации списка, где n — размер списка. Если список не был отсортирован, вы можете сначала отфильтровать, а затем отсортировать отфильтрованный список.

Если takeWhile не является вариантом, вы также можете найти индекс первого элемента вашего упорядоченного списка, который удовлетворяет условию. А затем используйте это, чтобы получить sublist. Ниже предполагается, что список отсортирован в порядке возрастания. Условный тест >= 3 необходим для поиска первого индекса, который не должен быть частью вашего отфильтрованного списка.

int index = IntStream.range(0, orderedList.size())
        .filter(i -> orderedList.get(i) >= 3).findFirst().orElse(orderedList.size());

List<Integer> filteredList = orderedList.subList(0, index);

Примечание. sublist — это вид части исходного списка. Изменение элементов в любом списке, начиная с 0 to index-1 включительно, будет отражено в другом.

Должно быть .orElse(orderedList.size()) Но вы можете избежать проверок O(n), используя int index = Collections.binarySearch(orderedList, 3); List<Integer> filteredList = orderedList.subList(0, index < 0? ~index: index);

Holger 02.09.2024 13:26

Другие вопросы по теме