How to filter a group with a precondition?

Viewed 94

Have the next code:

public static Map<String, Double> getSumOfPricesPerCategoryOver(){
    List<Videogame> number = videogames;
    
    Map<String, Double> counted = number
    .stream()
    .collect(Collectors.groupingBy(Videogame::getCategoria, Collectors.summingDouble(Videogame::getPrecio)));
    
    return counted;
    }

Problem

I would like to filter the group of categories that the sum of their prices are higher than 200 , any idea?

3 Answers

You can use partitioningBy to partition the map:

import static java.util.stream.Collectors.*;

Map<String, Map<Boolean, List<Videogame>>> updatedMap = 
        number.stream()
              .collect(groupingBy(Videogame::getCategoria, 
                       partitioningBy(e -> e.getPrice() > 200)));

Here, key is Categoria and value is another Map that partitions (true/false) into two categories of Videogame: 1) with price > 200 and with price <= 200.

Edit 1:
I saw other answers and reread the question. OP intends to filter the categories based on total sum of prices.

The construct for this requirement would be:

import static java.util.stream.Collectors.*;

// Key: Category, Value: Sum of all prices
// The resultant map contains only those categories that have total price > 200

Map<String, Integer> updatedMap = 
        number.stream()
              .collect(collectingAndThen(
                      groupingBy(Videogame::getCategoria, summingInt(Videogame::getPrice)), 
                      m -> {m.values().removeIf(e -> e < 200); return m;}));

You can filter the entries:

public static Map<String, Double> getSumOfPricesPerCategoryOver(){
    List<Videogame> number = videogames;

    Map<String, Double> counted = number
            .stream()
            .collect(Collectors.groupingBy(Videogame::getCategoria, Collectors.summingDouble(Videogame::getPrecio)))
            .entrySet().stream()
            .filter(categoryToTotalPrice -> categoryToTotalPrice.getValue() > 200)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    return counted;
}

Alternatively you could remove the entries before returning which will make it obvious that values over 200 are filterd out:

public static Map<String, Double> getSumOfPricesPerCategoryOver(){
    List<Videogame> number = videogames;

    Map<String, Double> counted = number
        .stream()
        .collect(Collectors.groupingBy(Videogame::getCategoria, Collectors.summingDouble(Videogame::getPrecio)));
    counted.values().removeIf(value -> value > 200);
    return counted;
}
Related