0

I have this code:

 SortedMap<String, Double> starsPerActivity = new TreeMap<>();
        for(Product p : products.values()) {
            for(Rating r : ratings) {
                if(r.getProductName() == p.getName()) {
                    starsPerActivity.put(p.getActivityName(), this.getStarsOfProduct(p.getName()));
                }
            }
        }
        return starsPerActivity;

And I want to rewrite this piece of code with streams. I tried, but I don't know how.

The method starsPerActivity() returns a map that associates a name of the activity to the average number of stars for the products belonging to that activity, with the activity names sorted alphabetically. Activities whose products have not been rated should not appear in the result.

Ciprian Oancea
  • 99
  • 1
  • 11

2 Answers2

5

You can use the third Collectors.toMap overload:

public static <T, K, U, M extends Map<K, U>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                         Function<? super T, ? extends U> valueMapper,
                         BinaryOperator<U> mergeFunction,
                         Supplier<M> mapFactory)

Which allows you to define what map implementation you'd like to use:

SortedMap<String, Double> starsPerActivity = products.values().stream()
     .filter(p -> ratings.stream()
         .anyMatch(r -> r.getProductName().equals(p.getName())))
     .collect(Collectors.toMap(
         Product::getActivityName, 
         p -> getStarsOfProduct(p.getName()), 
         Double::max, TreeMap::new
     ));

Also I noticed that you used r.getProductName() == p.getName() in your if statement, which is probably applied to Strings. This is discouraged, see: How do I compare strings in Java

Note that this implementation picks the rating with the highest value. You can change this behaviour by replacing Double::max with the logic you like. If you want the same behaviour you currently have then you could use this, which is close enough: (a, b) -> b which simply picks the latest put value.

Lino
  • 19,604
  • 6
  • 47
  • 65
0
SortedMap<String, Double> starsPerActivity = new TreeMap<>();
        products.values().forEach(p -> ratings.stream().filter(r -> r.getProductName().equals(p.getName()))
                .forEachOrdered(r -> starsPerActivity.put(p.getActivityName(), this.getStarsOfProduct(p.getName()))));
Ravinda Lakshan
  • 1,006
  • 14
  • 14