计算月度(yyyy-MM)同比的工具类

import java.time.YearMonth;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 计算同比
 */
public class YearOverYearComparison {
    /**
     * 直接从 VO 对象列表计算同比
     * @param currentData 当年数据列表
     * @param previousData 去年数据列表
     * @param keyExtractor 获取日期字段的函数
     * @param valueExtractor 获取数值字段的函数
     * @return 同比结果 Map<yyyy-MM, growthRate>
     *     使用demo:
     *          // 计算同比
     *         Map<String, Double> yearOverYearResult2 = YearOverYearComparison.calculateYearOverYear(
     *                 currentData, previousData,
     *                 MonthStatisticsVo::getYm,
     *                 MonthStatisticsVo::getAvgNum);
     */
    public static <T> Map<String, Double> calculateYearOverYear(
            List<T> currentData,
            List<T> previousData,
            Function<T, String> keyExtractor,
            Function<T, Double> valueExtractor) {

        Map<String, Double> currentMap = currentData.stream()
                .collect(Collectors.toMap(keyExtractor, valueExtractor));

        Map<String, Double> previousMap = previousData.stream()
                .collect(Collectors.toMap(keyExtractor, valueExtractor));

        return calculateYearOverYear(
                Collections.singletonList(currentMap),
                Collections.singletonList(previousMap)
        );
    }


    /**
     * 计算两年数据的同比
     * @param currentData 当年数据列表 Map<yyyy-MM, value>
     * @param previousData 去年数据列表 Map<yyyy-MM, value>
     * @return 同比结果 Map<yyyy-MM, growthRate>
     */
    public static Map<String, Double> calculateYearOverYear(
            List<Map<String, Double>> currentData,
            List<Map<String, Double>> previousData) {

        Map<String, Double> currentMap = convertToMap(currentData);
        Map<String, Double> previousMap = convertToMap(previousData);
        Map<String, Double> result = new HashMap<>();

        for (Map.Entry<String, Double> entry : currentMap.entrySet()) {
            String monthKey = entry.getKey();
            Double currentValue = entry.getValue();

            // 获取去年同期数据
            String previousMonthKey = getPreviousYearMonth(monthKey);
            Double previousValue = previousMap.get(previousMonthKey);

            if (previousValue != null && previousValue != 0) {
                // 计算同比增长率
                double growthRate = (currentValue - previousValue) / previousValue;
                result.put(monthKey, growthRate);
            }
        }

        return result;
    }

    /**
     * 将List<Map>转换为Map
     */
    private static Map<String, Double> convertToMap(List<Map<String, Double>> dataList) {
        Map<String, Double> map = new HashMap<>();
        for (Map<String, Double> data : dataList) {
            map.putAll(data);
        }
        return map;
    }

    /**
     * 获取去年同期月份
     */
    private static String getPreviousYearMonth(String month) {
        try {
            YearMonth yearMonth = YearMonth.parse(month);
            YearMonth previous = yearMonth.minusYears(1);
            return previous.toString();
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        // 示例数据
        List<Map<String, Double>> currentYearData = Arrays.asList(
                Map.of("2024-01", 100.0),
                Map.of("2024-02", 120.0)
        );

        List<Map<String, Double>> previousYearData = Arrays.asList(
                Map.of("2023-01", 90.0),
                Map.of("2023-02", 100.0),
                Map.of("2023-03", 95.0)
        );

        // 计算同比
        Map<String, Double> yearOverYearResult = YearOverYearComparison.calculateYearOverYear(
                currentYearData, previousYearData);

        // 输出结果
        yearOverYearResult.forEach((month, rate) ->
                System.out.println(month + " 同比增长: " + String.format("%.2f%%", rate * 100)));



        List<MonthStatisticsVo> currentData = Arrays.asList(
                new MonthStatisticsVo("2024-01", 100.0),
                new MonthStatisticsVo("2024-02", 120.0)
        );

        List<MonthStatisticsVo> previousData = Arrays.asList(
                new MonthStatisticsVo("2023-01", 90.0),
                new MonthStatisticsVo("2023-02", 100.0),
                new MonthStatisticsVo("2023-03", 95.0)
        );

        // 计算同比
        Map<String, Double> yearOverYearResult2 = YearOverYearComparison.calculateYearOverYear(
                currentData, previousData,
                MonthStatisticsVo::getYm,
                MonthStatisticsVo::getAvgNum);

        // 输出结果
        yearOverYearResult2.forEach((month, rate) ->
                System.out.println(month + " 同比增长: " + String.format("%.2f%%", rate * 100)));


    }

}

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;

@AllArgsConstructor
@Data
public class MonthStatisticsVo {
    @Schema(description = "年月")
    private String ym;
    @Schema(description = "平均数")
    private Double avgNum; 

}

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容