I have following JPQL statement:
select e as entity, c.type as config_type
from Entity e
left join Config c on e = c.entity
where c.type = (select t from Type t where t.name = 'SHOP')
I want to collect this result to Map grouping by Entity
. The value of map, should be List of config types. This list can be also empty if Entity
doesn't have any config specified. I have already wrote some method which accomplishes the task:
public Map<Entity, List<ConfigType>> getGroupedEntityToConfigTypesMap() {
return em.createNamedQuery(Entity.NQ_GET_ENTITY_TO_CONFIG_TYPE, Tuple.class)
.getResultStream()
.collect(Collectors.groupingBy(
tuple -> ((Entity) tuple.get("entity")),
Collectors.mapping(tuple -> ((ConfigType) tuple.get("config_type")),
Collectors.collectingAndThen(Collectors.toList(), list ->
list.stream()
.filter(Objects::nonNull)
.collect(Collectors.toUnmodifiableList())))
));
}
From my point of view, it doesn't look so good because while collecting values, I have to iterate one more time through every List and check if this list doesn't contain only null value, thus it is not so efficient.
Is there any better way to collect Tuple
to Map
with groupingBy more efficient and elegant than now? The goal is to collect also those entries which doesn't have any Configs but it should be mapped to empty list instead of Lists.of(null);
.
Maybe you want to check out Collections.filtering
. I tried to incorporate it into your solution and came up with a little bit more concise and efficient solution. But I have not tested it yet, sorry. Also note, that I returned the filtered objects as a Set
instead of a List
. Feel free to keep going with the List
if that fits your need best. And please hit me up if it worked or you have any other questions.
Stream.of(tuple)
.collect(groupingBy(
record -> (tuple.get("entity")),
mapping(record -> (tuple.get("config_type")),
Collectors.filtering(Objects::nonNull, Collectors.toSet()))
));