使用java 8流转换对象

时间:2016-10-27 13:26:21

标签: java java-8 java-stream collectors

我有这两个对象:

public class Service {
    private String cod;
    private String name;
    private String table;
    private String selo;
    private BigDecimal value;
    private BigDecimal desconto;
    private BigDecimal baseCalculo;
    private Integer amountExcedente;
    private String descontoLei;

... G and S
}

并且

    public class ServiceResumo {
        private String name;
        private int amount;
        private BigDecimal value;
        private String acao;

        public ServiceResumo(String name, BigDecimal value, int amount) {
            this.name = name;
            this.value = value;
            this.amount = amount;
        }
    ...G and S
    }

所以我有很多服务,

List<Service> servicos = new ArrayList<Service>();
servicos.add(new Service("Service A", 3,.....)); //Service A -> Name and 3 -> value
servicos.add(new Service("Service B", 4.....));
servicos.add(new Service("Service A", 2,.....));
servicos.add(new Service("Service C", 3,.....));
servicos.add(new Service("Service D", 5,.....));
servicos.add(new Service("Service A", 6,.....));
servicos.add(new Service("Service A", 8,.....));
servicos.add(new Service("Service B", 9, .....));

那么我可以在java 8中使用stream将其减少为ServiceResumo列表吗?有点像这样:

|名字|价值|金额|

服务A | 21 | 4 |

服务B | 13 | 2 |

服务C | 3 | 1 |

服务D | 5 | 1 |

1 个答案:

答案 0 :(得分:2)

通过组合三个收藏家

,您可以获得所需的结果
  • 有一个内置的收集器groupingBy,它允许按名称等属性对元素进行分组。
  • 为了将组聚合到ServicoResumo对象中,您需要一个能够将Service个实例聚合到这样的ServicoResumo实例中的收集器。您必须为此创建一个自定义收集器。
  • 由于将groupingBy收集器与您的自定义收集器合并的结果为Map<PropertyType,AggregationResult>,即Map<String,ServicoResumo>,您需要一个后处理步骤将其转换为List<ServicoResumo> },可以通过collectingAndThen
  • 完成
List<ServiceResumo> result=servicos.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.groupingBy(Service::getName,
            Collector.of(()->new ServiceResumo(null, BigDecimal.ZERO, 0),
                (r,s) -> {
                    r.setName(s.getName());
                    r.setValue(r.getValue().add(s.getValue()));
                    r.setAmount(r.getAmount()+1);
                },
                (r1,r2) -> {
                    r1.setValue(r1.getValue().add(r2.getValue()));
                    r1.setAmount(r1.getAmount()+r2.getAmount());
                    return r1;
                })),
            m -> new ArrayList<>(m.values())
    ));

groupingBy的第一个参数,Service::getName指定构成分组条件的属性。 collectingAndThen的第二个参数m -> new ArrayList<>(m.values())说明了如何将Map转换为所需的List

介于两者之间的重要部分是通过Collector.of创建的自定义收藏夹。请参阅Collector documentation“Mutable Reduction” section of the package documentation以了解收藏家的工作方式。