Допустим, у меня есть следующее:
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, или он всегда проверяет все элементы?
Если он проверяет все элементы, есть ли более разумный способ фильтровать элементы в ситуации с упорядоченным списком?




В вашем сценарии, поскольку вы возвращаете список со всеми элементами, соответствующими фильтру, filter() применяется ко всем элементам в потоке.
Если вы хотите остановить обработку, когда определенное условие истинно/ложно, вы можете использовать takeWhile() из Java 9:
orderedList.stream().takeWhile(v -> v < 3).forEach(System.out::println);
Возможно, обратите внимание, что takeWhile был добавлен в Java 9, поскольку, похоже, многие люди все еще используют Java 8.
"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);
вот почему
takeWhile()