Skip to content
Advertisement

Java8 Streams: How to preserve the value before map to be accessed by collect/groupingBy functions

I’m using Java8 Streams to iterate through a list and for each of the element I invoke map and then I need to aggregate the results. My problem is that when I call groupingBy I also need to access the original object before calling map. Here is a snippet:

list.stream() //
          .filter(item -> item.getType() == HUMAN) //
          .map(item -> manager.itemToHuman(item.getId())) //
          .filter(Objects::nonNull) //
          .collect(Collectors.groupingBy(Human::getAge, Collectors.summarizingLong(item.getCount())));

The problem is with the call to Collectors.summarizingLong(item.getCount()) since item at this point is NOT accessible. Is there an elegant way to overcome this?

Advertisement

Answer

After doing map() stream transformed into Stream<Human> so you can’t use item object in the collector.

You can transform item into a pair of Human object and count using SimpleEntry then use it on the collector.

list.stream() 
    .filter(item -> item.getType() == HUMAN) 
    .map(item -> 
        new AbstractMap.SimpleEntry<>(manager.itemToHuman(item.getId()), item.getCount()))
    .filter(entry -> Objects.nonNull(entry.getKey()))
    .collect(Collectors.groupingBy(entry -> entry.getKey().getAge(), 
             Collectors.summarizingLong(Map.Entry::getValue)));
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement