Как подсчитать количество элементов по одному из полей объектов списка List?

Нужно подсчитать количество элементов списка, по одному из полей. Допустим список имеет в себе такие объекты:

ObservableList<Ticket> filteredData = FXCollections.observableArrayList();
        filteredData.add(new Ticket ("1","2","true"));
        filteredData.add(new Ticket ("7","2","true"));
        filteredData.add(new Ticket ("2","3","true"));
        filteredData.add(new Ticket ("3","2","true"));
        filteredData.add(new Ticket ("4","1","true"));
        filteredData.add(new Ticket ("3","1","true"));

Нужно подсчитать сколько объектов в данном списке, у которых второе поле совпадает, объекты могут меняться, так как их поля могут иметь любое строковое значение, ввод происходит через графический интерфейс. Для этого списка по второму полю есть 3 совпадающих объекта с значением 2, 2 совпадающих объекта с значением 1.


Ответы (2 шт):

Автор решения: Nowhere Man

Подсчёт количества значений в данном поле приведёт к мапе, где ключом будет строка, а значением -- количество.

Предположим, класс Ticket имеет геттер для второго поля public String getField2(), тогда можно получить мапу:

Map<String, Integer> field2Counts = filteredData
    .stream()
    .collect(Collectors.groupingBy(
        Ticket::getField2,
        Collectors.summingInt(t -> 1)
    ));

Аналогично без StreamAPI с использованием Map::merge:

Map<String, Integer> counts = new HashMap<>();
for (Ticket t : filteredData) {
    counts.merge(t.getField2(), 1, Integer::sum);
}
→ Ссылка
Автор решения: Дмитрий

Я бы написал такой метод:

public static <K, V> Map<V, Long> groupingBy(Iterable<K> itrb, Function<K, V> extracter) {
    return StreamSupport.stream(itrb.spliterator(), false)
            .map(extracter)
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}

Реализация максимально абстрактная, ее можно использовать с любыми коллекциями, содержащие любой контент.

Вызываем метод, передавая в нее коллекцию и поле, по которому хотим группировать данные.

Map<String, Long> groupingBy = groupingBy(filteredData, Ticket::getParam1);

В данном примере вызова filteredData-наша коллекция, а а Ticket::getParam1 - вызов геттера поля с условным именем param1, по которому мы хоти произвести расчет.

→ Ссылка