Stream Java – поиск максимального значения свойства для каждой группы объектов
Есть list объектов:
SuvLogDto{
private String system;
private Date dateTime;
private String x;
...
}
Из этого листа нужно выбрать элементы у которых dateTime будет максимальной в его группе, образованной по свойству system.
По сути нужно сделать группировку по system, а потом внутри образовавшихся групп выбрать максимальный по dateTime элемент.
Как пытаюсь это сделать:
Map<String, SuvLogDto> mostExpensives = suvLogDtos.stream().collect(Collectors.toMap(SuvLogDto::getSystem, Function.identity()),
BinaryOperator.maxBy(Comparator.comparing(SuvLogDto::getDateTime)));
Это должно подойти, потому что:
<T,K,U> Collector<T,?,Map<K,U>> toMap(
Function<? super T,? extends K> keyMapper,
Function<? super T,? extends U> valueMapper,
BinaryOperator<U> mergeFunction)
keyMapper: функция сопоставления для создания ключей сопоставления для каждого элемента входного потока. valueMapper: функция сопоставления для создания значений сопоставления для каждого элемента входного потока. mergeFunction: бинарный оператор, предназначенный для разрешения коллизий между значениями, связанными с одним и тем же ключом. Входными данными для этой функции являются значения, принадлежащие одному и тому же ключу.
Но Java мне выдает ошибку:
Cannot resolve method 'collect(java.util.stream.Collector<T,capture<?>,java.util.Map<K,U>>, java.util.function.BinaryOperator)'
Что не так в алгоритме? Как можно поправить?
Ответы (1 шт):
У вас в коде небольшая опечатка, так как скобка закрыта до того как был указан третий аргумент в коллекторе toMap, должно быть так:
List<SuvLogDto> suvLogDtos = Arrays.asList(
new SuvLogDto("sys1", new Date(System.currentTimeMillis() - 1000), "1 - 1000"),
new SuvLogDto("abc", new Date(System.currentTimeMillis() - 2000), "abc-2000"),
new SuvLogDto("sys1", new Date(System.currentTimeMillis() - 2000), "1 - 2000"),
new SuvLogDto("xyz", new Date(System.currentTimeMillis() - 3000), "xyz - 3K"),
new SuvLogDto("abc", new Date(System.currentTimeMillis() - 500), "abc - 500")
);
Map<String, SuvLogDto> mostExpensives = suvLogDtos
.stream()
.collect(Collectors.toMap(
SuvLogDto::getSystem,
Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(SuvLogDto::getDateTime))
));
mostExpensives.forEach((k, v) -> System.out.println(k + ": " + v));
Вывод результата:
sys1: SuvLogDto[system=sys1, date=Fri Sep 16 17:08:53 GMT 2022, x=1 - 1000]
abc: SuvLogDto[system=abc, date=Fri Sep 16 17:08:53 GMT 2022, x=abc - 500]
xyz: SuvLogDto[system=xyz, date=Fri Sep 16 17:08:51 GMT 2022, x=xyz - 3K]
Также можно дополнительно указать LinkedHashMap::new в качестве четвертого аргумента, чтобы получить мапу, поддерживающую порядок вставки (если нужно).