Java 8 个流映射分组依据后的缩减值

Java 8 Streams Map Reduced Value after Group By

使用 Java 流,我想计算给定项目列表的成本,按类型分组。获得成本后,我想将 BigDecimal 映射到格式化的货币字符串。是否可以映射简化值和分组值?

import java.math.BigDecimal;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.Map;

public class MyClass {
    public static class Item {
        private String name;
        private String type;
        private BigDecimal cost;
        
        public Item(String name, String type, BigDecimal cost) {
            this.name = name;
            this.type = type;
            this.cost = cost;
        }
        
        public String getName() {
            return name;
        }
        
        public String getType() {
            return type;
        }
        
        public BigDecimal getCost() {
            return cost;
        }
        
    }

    public static void main(String args[]) {
      List<Item> items = new ArrayList<>();
      items.add(new Item("Doll", "Toy", new BigDecimal("2.00")));
      items.add(new Item("Hamburger", "Food", new BigDecimal("8.00")));
      items.add(new Item("Car", "Toy", new BigDecimal("4.00")));
      items.add(new Item("Salad", "Food", new BigDecimal("1.00")));
      
      Map<String, BigDecimal> itemTypesAndCosts = items.stream().collect(Collectors.groupingBy(Item::getType, Collectors.reducing(BigDecimal.ZERO, Item::getCost, BigDecimal::add)));
      
      // prints {Food=9.00, Toy=6.00}
      // I would like it to map big decimal to formatted string to print {Food=".00", Toy=".00"}
      
      System.out.println(itemTypesAndCosts);
    }
}

您可以将还原收集器包装在 CollectingAndThen 收集器中,该收集器采用下游收集器和整理器功能。 CollectingAndThen 是一个特殊的收集器,它允许我们在收集结束后直接对结果执行另一个操作。将您的地图类型更改为 Map<String, String> 并执行 :

Map<String, String> itemTypesAndCosts = items.stream().collect(Collectors.groupingBy(Item::getType,
        Collectors.collectingAndThen(
                Collectors.reducing(BigDecimal.ZERO, Item::getCost, BigDecimal::add),
                total -> new DecimalFormat("'$'0.00").format(total))
));

//output: {Food=.00, Toy=.00}