Stream分组后并计算各项之和

1、Stream分组后并计算各项之和


import static java.util.Comparator.comparing;
/**
     * 分组后并计算各项之和
     */
    @Test
    public void testGroupByAndSum() {
        List<User> users = new ArrayList<>();

        Boolean mulFlag = true;
        Map<String, List<User>> collect = mulFlag ?
                // 多个字段进行分组
                users.stream().collect(Collectors.groupingBy(item -> item.getId() + '-' + item.getName())) :
                // 单字段进行分组
                users.stream().collect(Collectors.groupingBy(User::getName));


        List<UserStrings> userStrings = new ArrayList<>();
        Map<String, List<UserStrings>> collectStrings = mulFlag ?
                // 多个字段进行分组
                userStrings.stream().collect(Collectors.groupingBy(item -> item.getId() + '-' + item.getName())) :
                // 单字段进行分组
                userStrings.stream().collect(Collectors.groupingBy(UserStrings::getName));
        List<UserStrings> collectResultStrings = new ArrayList<>();
        // 对分组后的集合进行计算各项的总和  String
        for (Map.Entry<String, List<UserStrings>> entry : collectStrings.entrySet()) {
            // 分组后计算总指标 (此时id、age为String类型)
            UserStrings temp1 = MathUtil.mapperSumString(UserStrings.class,
                    entry.getValue(),
                    UserStrings::getId,
                    UserStrings::getAge);
            UserStrings user = entry.getValue().get(0);
            collectResultStrings.add(temp1);

        }

        // 对分组后的集合进行计算各项的总和  Double
        List<UserDouble> collectResult = new ArrayList<>();
        List<UserDouble> userDouble = new ArrayList<>();
        Map<String, List<UserDouble>> collectDouble = mulFlag ?
                // 多个字段进行分组
                userDouble.stream().collect(Collectors.groupingBy(item -> item.getId() + '-' + item.getName())) :
                // 单字段进行分组
                userDouble.stream().collect(Collectors.groupingBy(UserDouble::getName));
        for (Map.Entry<String, List<UserDouble>> entry : collectDouble.entrySet()) {

            // 分组后计算 (此时id、age为Double类型)
            UserDouble temp2 = MathUtil.mapperSum(UserDouble.class,
                    entry.getValue(),
                    UserDouble::getId,
                    UserDouble::getAge);
            UserDouble user = entry.getValue().get(0);
            collectResult.add(temp2);
        }


        // 对集合进行排序
        collectResult = collectResult.stream().sorted(comparing(UserDouble::getAge).reversed()).collect(Collectors.toList());
    }

2、涉及到的工具类

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class MathUtil {

    /**
     * 返回字符串转double
     *
     * @param doubleValue
     * @return
     */
    public static Double getDouble(String doubleValue) {
        return StringUtils.hasText(doubleValue) ? new Double(doubleValue) : 0;
    }

    public static Double str2Double(String doubleValue) {
        return Double.valueOf(doubleValue);
    }

    /**
     * 返回多个字符串转double之和
     *
     * @param doubleFirstValue
     * @param doubleSecondValue
     * @param doubleThirdValue
     * @return
     */
    public static double getDoubleMul(String doubleFirstValue, String doubleSecondValue, String doubleThirdValue) {
        return addDouble(str2Double(doubleFirstValue), str2Double(doubleSecondValue), str2Double(doubleThirdValue));
    }

    /**
     * 返回多个字符串转double之和(返回string)
     *
     * @param doubleFirstValue
     * @param doubleSecondValue
     * @param doubleThirdValue
     * @return
     */
    public static String getDoubleMulStr(String doubleFirstValue, String doubleSecondValue, String doubleThirdValue) {
        return getDouble2String(addDouble(getDouble(doubleFirstValue), getDouble(doubleSecondValue), getDouble(doubleThirdValue)));
    }

    public static String getDoubleMulStr(String doubleFirstValue, String doubleSecondValue, String doubleThirdValue, String doubleFourthValue) {
        return getDouble2String(addDouble(getDouble(doubleFirstValue), getDouble(doubleSecondValue), getDouble(doubleThirdValue), getDouble(doubleFourthValue)));
    }

    /**
     * 加法运算
     *
     * @param m1
     * @param m2
     * @return
     */
    public static double addDouble(double m1, double m2, double m3) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        BigDecimal p3 = new BigDecimal(Double.toString(m3));
        return p1.add(p2).add(p3).doubleValue();
    }

    /**
     * 加法运算
     *
     * @param m1
     * @param m2
     * @return
     */
    public static double addDouble(double m1, double m2, double m3, double m4) {
        BigDecimal p1 = new BigDecimal(Double.toString(m1));
        BigDecimal p2 = new BigDecimal(Double.toString(m2));
        BigDecimal p3 = new BigDecimal(Double.toString(m3));
        BigDecimal p4 = new BigDecimal(Double.toString(m4));
        return p1.add(p2).add(p3).add(p4).doubleValue();
    }

    public static String getDouble2String(Double doubleValue) {
        return String.valueOf(new BigDecimal(String.valueOf(doubleValue)));
    }

    /**
     * 针对字符串的数值型
     * 利用反射形成合计数据
     * 通过clazz.newInstance()构造合计数据行
     * 循环处理每一个IFunction,可以看出1、2出代码就是上方获取aa、bb累计
     * 通过get方法获取对应的set方法
     * 给第一步构造的数据执行set方法赋值
     *
     * @param clazz
     * @param list
     * @param mappers
     * @param 
     * @return
     */
    public static <T> T mapperSumString(Class<T> clazz, List<T> list, IFunction<? super T, ? extends String>... mappers) {
        try {
            List<String> data;
            T o = clazz.newInstance();
            for (IFunction<? super T, ? extends String> mapper : mappers) {
                data = list.stream().map(mapper).filter(Objects::nonNull).collect(Collectors.toList());
                String add = getDouble2String(data.stream().mapToDouble(MathUtil::getDouble).sum());
                String setMethod = setMethodString(mapper);
                Method method = clazz.getMethod(setMethod, String.class);
                method.invoke(o, add);
            }
            return o;
        } catch (Exception e) {
            throw new ServiceException("数据异常!");
        }
    }

    /**
     * 针对数值型
     * @param clazz
     * @param list
     * @param mappers
     * @return
     * @param 
     */
    public static <T> T mapperSum(Class<T> clazz, List<T> list, IFunction<? super T, ? extends Double>... mappers) {
        try {
            List<Double> data;
            T o = clazz.newInstance();
            for (IFunction<? super T, ? extends Double> mapper : mappers) {
                data = list.stream().map(mapper).filter(Objects::nonNull).collect(Collectors.toList());
                Double add = data.stream().mapToDouble(x ->x).sum();
                String setMethod = setMethod(mapper);
                Method method = clazz.getMethod(setMethod, Integer.class);
                method.invoke(o, add);
            }
            return o;
        } catch (Exception e) {
            throw new ServiceException("数据异常!");
        }
    }

    private static <T> String setMethodString(IFunction<? super T, ? extends String> func) {
        String implMethodName = func.getImplMethodName();
        String substring = implMethodName.substring(3);
        return "set" + substring;
    }

    private static <T> String setMethod(IFunction<? super T, ? extends Double> func) {
        String implMethodName = func.getImplMethodName();
        String substring = implMethodName.substring(3);
        return "set" + substring;
    }

    public static void main(String[] args) {
        /*Double doubleMul = getDoubleMul("1111.11", "2222.22", "3333.39");
        System.out.println(getDouble2String(doubleMul));
        System.out.println(getDoubleMulStr("1111.11", "2222.22", "3333.39"));

        System.out.println(getDoubleMulStr("", "2222.22", "3333.39"));
        System.out.println(getDoubleMulStr(null, "2222.22", "3333.39"));*/

        String annual = MathUtil.getDoubleMulStr("1111.11", "2222.22", "3333.34", "4444.44");
    }
}

3、涉及到的IFunction接口

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.function.Function;

@FunctionalInterface
public interface IFunction<T, R> extends Function<T, R>, Serializable {

    default SerializedLambda getSerializedLambda(){
        Method write;
        try {
            write = this.getClass().getDeclaredMethod("writeReplace");
            write.setAccessible(true);
            return (SerializedLambda) write.invoke(this);
        } catch (Exception e) {
            throw new IllegalArgumentException();
        }
    }

    default String getImplClass() {
        return getSerializedLambda().getImplClass();
    }

    default String getImplMethodName() {
        return getSerializedLambda().getImplMethodName();
    }
}

你可能感兴趣的:(stream,Java,java,开发语言)