Shvalb
Shvalb

Reputation: 1933

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?

Upvotes: 1

Views: 914

Answers (1)

Eklavya
Eklavya

Reputation: 18420

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)));

Upvotes: 1

Related Questions