В чём разница терминальных операций в Java Stream API: count() и collect(Collectors.counting())?
count()
и
collect(Collectors.counting())
Не дублирующий ли это функционал? Или есть какая-то разница, тогда что предпочтительнее использовать?
Я пока не нашёл ситуаций, где второй не мог бы заменить первый.
Ответы (2 шт):
Вместо .collect(Collectors.counting()) лучше использовать .count(), т.к. это более читаемо и по-сути делает то же самое.
Но Collectors.counting() может пригодиться для других целей, например его можно использовать в коллекторах вроде Collectors.groupingBy, Collectors.collectingAndThen и т.д.
Пример
Есть класс продукта:
public class Product {
private final String name; // имя продукта
private final String manufacturerName; // имя производителя
// далле конструкоры, геттеры и т.д.
//...
}
и список продуктов:
List<Product> products = Arrays.asList(
new Product("product1", "manufacturer1"),
new Product("product2", "manufacturer2"),
new Product("product3", "manufacturer1")
);
Допустим, что нужно получить Map, в котором ключ - это имя производителя, а значение - количество произведенных продуктов.
Сделать это можно с использованием Collectors.counting (будет выглядеть менее громоздко, если использовать статические импорты):
products
.stream()
.collect(Collectors.groupingBy(Product::getManufacturerName, Collectors.counting()))
Результат выполнения: {manufacturer1=2, manufacturer2=1}
Терминальный метод count() обладает одной интересной собенностью - если в цепочке промежуточных операций не будет операций изменения количества данных источника (например filter()), то эти промежуточные операции не будут выполняться. По сути компилятор производит оптимизацию для ускорения получения результата. Например:
list.stream().map(Object::toString).peek(System.out::println).count();
ничего не выведет на консоль, в то время как collect(Collectors.counting()) обеспечит стандартное выполнение всех методов в цепочке.