首先我还是吐吐槽,话说题主你也不给一个期盼的结果,你问题的描述在我看来其实不太清楚你想要什么结果,我指的是具体的返回类型,看了你下面自己的答复,才知道你想要个map,虽然这个可能在你看来无伤大雅,但是我觉得又不是回答什么方案问题,你肯定是希望有一种代码写法,并且可以执行的,那给一个输入+输出的格式不好么,因为只要确认了输入输出,其实起码对于我们帮你想办法的人来说,就可以限定了很多写法和不必要的思考方向了,节约的大家的时间◐▽◑
还是言归正传,说说我自己的想法,这类问题其实我记得我也回答了几个了叭。。。
一般我的思路即: 当没有合适我需求的jdk stream api提供时,都采用自定义Collector的方式解决
题主的输入为List,输出为Map,而jdk中提供的返回map的一般也是Collectors.toMap,Collectors.groupBy,但是他们都不太符合题主的需求,因此还是自定义Collector的方式比较简单直接,当然题主已经给了一个回答了,在只要完成需求的目标前提下,其实都是可以的,所以我下面这种Collector只是算提供另一个思路吧(如果从使用角度来说,Collector使用起来相对简单)
@RequiredArgsConstructor
public class CustomSumByFieldCollector implements Collector, Map> {
private final List fieldNames;
private static final BiFunction GET_VALUE_FUN = (beanMap, fieldName) -> {
Double value = (Double) beanMap.getOrDefault(fieldName, Double.valueOf(0d));
return new BigDecimal(value);
};
@Override
public Supplier> supplier() {
return HashMap::new;
}
@Override
public BiConsumer, Entity> accumulator() {
return (map, entity) -> {
BeanMap beanMap = BeanMap.create(entity);
fieldNames.forEach(fieldName -> map.merge(fieldName, GET_VALUE_FUN.apply(beanMap, fieldName), BigDecimal::add));
};
}
@Override
public BinaryOperator> combiner() {
return (map1, map2) -> {
map1.putAll(map2);
return map1;
};
}
@Override
public Function, Map> finisher() {
return Function.identity();
}
@Override
public Set characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
}
}
上面有用到BeanMap是spring-core里的一个工具类,就是把entity转换为map,当然你可以使用其他的转换工具,例如apache的BeanUtils
而使用这个Collector的时候,直接new一个CustomSumByFieldCollector即可
public static void main(String[] args) {
List list = new ArrayList<>();
List keyList = Arrays.asList("t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", "t10", "t11", "t12", "amount");
Map map = list.stream().collect(new CustomSumByFieldCollector(keyList));
}
由于题主也没有给测试用例,我也懒得写了哈,见谅,哈哈哈哈(* ̄ω ̄),所以这个代码没有测过,不过思路这样的,一般自定义Collector可以解决100%的stream收集问题,起码对我来说100%,哈哈哈,谁用谁说好,如果你对于自定义Collector不太清楚,可以看一下我很早之前的一个说明吧
Java8 collector接口的定制实现
拜了个拜ヾ( ̄▽ ̄)