Как отсортировать List объектов с двумя полями
Имеется List<Consumer> myList, в котором объект представлен полем consumer и полем termClarification.
Поля заказчиков повторяются, поля уточнений сроков имеют два типа: "есть", "нет".
Необходимо вывести заказчиков и процент соотношения уточнений сроков.
Я использовал код, который группирует уникальных заказчиков и количество уточнений:
Map<Consumer, Integer> consumerMap = new HashMap<>();
for (Consumer object : consumerList) {
if (consumerMap.containsKey(object)) {
consumerMap.put(object, consumerMap.get(object) + 1);
} else {
consumerMap.put(object, 1);
}
}
Как отсортировать значения в процентном соотношении?
Ответы (1 шт):
Во-первых, начиная с Java 8 Consumer -- это функциональный интерфейс с методом void accept(T t). Во избежание недоразумений стоит использовать другое название класса, например, MyConsumer или Customer.
Имеется List myList, в котором объект представлен полем
consumerи полемtermClarification.
То есть, предположим, что класс можно представить так:Consumer
@Data // lombok-аннотация для генерации геттеров/сеттеров/equals/hashCode/toString
class MyConsumer {
private String consumer;
private boolean termClarification;
}
Для расчёта процента соотношений уточнений нужно вычислить количество объектов, где termsClarification == true и поделить на общее количество объектов. Для накопления статистики можно использовать массив int[].
Для расчёта можно применить Stream API и коллектор toMap с функцией слияния.
List<MyCustomer> customers; // ...
Map<String, int[]> stats = customers.stream()
.collect(Collectors.toMap(
MyCustomer::getConsumer, // ключ - поле consumer
customer -> new int[]{1, customer.isTermClarification() ? 1 : 0},
(arr1, arr2) -> new int[]{arr1[0] + arr2[0], arr1[1] + arr2[1]}
));
Статистика stats - хэш-мапа, которая не поддерживает порядок сортировки.
Для сортировки по значениям нужно применить компаратор по значению частоты:
stats.entrySet()
.stream() // Stream<Map.Entry<String, int[]>>
.sorted(Map.Entry.comparingByValue(
Comparator.comparingDouble((int[] arr) -> (double) arr[1] / arr[0]).reversed()
).thenComparing(Map.Entry.comparingByKey())
)
.forEach(e -> System.out.println(e.getKey() + ": " + (double) e.getValue()[1] / e.getValue()[0]));
Примечание: код не тестирован