gringogordo
gringogordo

Reputation: 2130

How do you call a method from within a Collector in Java 8 Streaming?

I have a bit of code that is working functionally as I want it to:

private Map<Florist, EnumSet<Flower>> localMethod(List<FlowerSellers> branchList) {
    Map<Florist, EnumSet<Flower>> availableFlowers = new EnumMap<>(Florist.class);

    branchList.stream()
              .filter(f -> f instanceof FlorestFranchised)
              .forEach(f -> availableFlowers.put(
                      FlorestHelperClass.florestTypeForKey(f.id()), 
                      ((FlorestFranchised) f).getFlowers()));

    return availableFlowers;
}

For sake of argument the helper class method is:

public static Florist FlorestTypeForKey(String id) {
    return FLOREST_MAP.get(id);
}

I would like to do this with a collector instead so I wanted to do this ...

return branchList.stream()
                 .filter(p -> p instanceof FlorestFranchised)
                 .map(p -> (FlorestFranchised) p)
                 .collect(Collectors.toMap(
                         FlorestFranchised::getId,  
                         FlorestFranchised::getFlowers));

But obviously this fails because it is not doing the helper class lookup and so rather than returning a map of <Florest, Flowers> it is returning <String, Flowers>

This fails though :

return branchList.stream()
                 .filter(p -> p instanceof FlorestFranchised)
                 .map(p -> (FlorestFranchised) p)
                 .collect(Collectors.toMap(
                         FlorestHelperClass.florestTypeForKey(FlorestFranchised::getId),
                         FlorestFranchised::getFlowers));

Can anyone tell me how I should call the lookup methods (FlorestHelperClass.florestTypeForKey) in the collector? Is it possible?

Upvotes: 2

Views: 486

Answers (2)

Eklavya
Eklavya

Reputation: 18410

You can map first as AbstractMap.SimpleEntry pair then use Collectors.toMap

return branchList
    .stream()
    .filter(p -> p instanceof FlorestFranchised )
    .map(p -> (FlorestFranchised) p )
    .map(p -> new AbstractMap.SimpleEntry<>(
                 FlorestHelperClass.florestTypeForKey(p.getId()), p.getFlowers()))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

Upvotes: 2

Nikolas
Nikolas

Reputation: 44368

Collectors.toMap requires two functions creating a key and value respectively from the value passed into the collect method. Therefore you can do this:

return branchList.stream()
    .filter(p -> p instanceof FlorestFranchised)
    .map(p -> (FlorestFranchised) p)
    .collect(Collectors.toMap(
        p -> FlorestHelperClass.florestTypeForKey(p.getId()),   // key
        p -> p.getFlowers()                                     // value
));

The last lambda expression can be replaced with FlorestFranchised::getFlowers.

Upvotes: 3

Related Questions