java 计算比例 java计算同比

您所在的位置:网站首页 python计算同比增长率 java 计算比例 java计算同比

java 计算比例 java计算同比

2023-06-21 14:43| 来源: 网络整理| 查看: 265

做数据统计的时候经常会有这样的需求,给你一组历史数据,包含两列,一列是日期,一列是数值,让你计算出同比环比。

其实这样的需求很多,而且不复杂,但是用SQL并不好实现。

一、自定义子类版

我尝试用java实现一下,下面是一个日期生成器,方便后面造案例数据

public class DateUtils { /** * 最近30天生成器,不包含当天 * * @param today * @param interval=30 * @return */ public static List generateLast30Days(LocalDate today, int interval) { List localDates = new ArrayList(); for (int i = interval; i > 0; i--) { LocalDate localDate = today.minusDays(i); localDates.add(localDate); } return localDates; } /** * 最近12个月生成器,不包括本月 * * @param today * @param interval=12 * @return */ public static List generateLast12Months(LocalDate today, int interval) { List localDates = new ArrayList(); for (int i = interval; i > 0; i--) { LocalDate localDate = today.minusMonths(i); localDates.add(localDate.withDayOfMonth(1)); } return localDates; } /** * 指定时间单元前一个时间点的值 * 比如:today=2022-10-01, * timeUnit=Days=>2022-09-30 * timeUnit=MONTHS=>2022-09-01 * timeUnit=YEARS=>2021-10-01 * @param today * @param timeUnit * @return */ public static LocalDate previousDate(LocalDate today, ChronoUnit timeUnit) { switch (timeUnit) { case DAYS: return today.minusDays(1); case MONTHS: return today.minusMonths(1); case YEARS: return today.minusYears(1); default: throw new IllegalArgumentException("不支持的时间区间类型!"); } } public static LocalDate nextDate(LocalDate today, ChronoUnit timeUnit) { switch (timeUnit) { case DAYS: return today.plusDays(1); case MONTHS: return today.plusMonths(1); case YEARS: return today.plusYears(1); default: throw new IllegalArgumentException("不支持的时间区间类型!"); } } }

接下来,我们定义一个模型,只有两个属性

public class Model { private String dt; private Double num; public Model(String dt, Double num) { this.dt = dt; this.num = num; } public String getDt() { return dt; } public Double getNum() { return num; } @Override public String toString() { return "Model{" + "dt='" + dt + '\'' + ", num=" + num + '}'; } }

接下来是要输出的模型,在上面的基础上,增加了环比、同比

import java.text.DecimalFormat; /** * @Author : wangbin * @Date : 2023/3/13 13:30 * @Description: */ public class ModelPlus extends Model{ private static final DecimalFormat decimalFormat = new DecimalFormat("#.##"); private Double basisRate; private Double loopRate; public ModelPlus(String dt, Double num) { super(dt, num); } public static ModelPlus build(Model model){ return new ModelPlus(model.getDt(), model.getNum()); } public Double getBasisRate() { return basisRate; } public void setBasisRate(Double basisRate) { this.basisRate = basisRate; } public Double getLoopRate() { return loopRate; } public void setLoopRate(Double loopRate) { this.loopRate = loopRate; } @Override public String toString() { return "ModelPlus{" + "dt="+this.getDt()+ ",num="+decimalFormat.format(this.getNum())+ ",basisRate=" + decimalFormat.format(basisRate) + ", loopRate=" + decimalFormat.format(loopRate) + '}'; } }

最后是我们的核心逻辑,先随机生成近18个月的数据,然后计算出环比、同比

import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; import java.util.List; import java.util.Map; import java.util.Random; import java.util.stream.Collectors; public class Main { private final static DateTimeFormatter formats=DateTimeFormatter.ofPattern("yyyy-MM"); private final static Random rand=new Random(); public static void main(String[] args) { List models = build(); Map map = models.stream().collect(Collectors.toMap(Model::getDt, Model::getNum)); List list = models.stream().map(model -> { ModelPlus plus = ModelPlus.build(model); String dt = plus.getDt(); Double num = plus.getNum(); String lastM = getLastMonth(dt); String lastYM = getLastYearMonth(dt); Double lastMV = map.get(lastM); Double lastYMV = map.get(lastYM); Double basisRate = basisRate(lastYMV, num); plus.setBasisRate(basisRate); Double loopRate = basisRate(lastMV, num); plus.setLoopRate(loopRate); return plus; }).collect(Collectors.toList()); for (ModelPlus modelPlus : list) { System.out.println(modelPlus); } } //同比或环比 public static Double basisRate(Double lastVal,Double thisVal){ if(lastVal==null||lastVal==0d){ return 0d; } return 100*(thisVal-lastVal)/lastVal; } //上月 public static String getLastMonth(String month){ DateTimeFormatter format = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM") .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) .toFormatter(); LocalDate parse = LocalDate.from(format.parse(month)); LocalDate lastMonth = parse.minusMonths(1); return format.format(lastMonth); } //去年同月 public static String getLastYearMonth(String month){ DateTimeFormatter format = new DateTimeFormatterBuilder() .appendPattern("yyyy-MM") .parseDefaulting(ChronoField.DAY_OF_MONTH, 1) .toFormatter(); LocalDate parse = LocalDate.from(format.parse(month)); LocalDate lastMonth = parse.minusYears(1); return format.format(lastMonth); } public static List build() { List localDates = DateUtils.generateLast12Months(LocalDate.now(), 18); return localDates.stream().map(localDate -> { String dt = formats.format(localDate); double v = 100 * rand.nextDouble(); return new Model(dt, v); }).collect(Collectors.toList()); } }

输出:

ModelPlus{dt=2021-09,num=47.67,basisRate=0, loopRate=0} ModelPlus{dt=2021-10,num=22.03,basisRate=0, loopRate=-53.79} ModelPlus{dt=2021-11,num=57.69,basisRate=0, loopRate=161.89} ModelPlus{dt=2021-12,num=85.7,basisRate=0, loopRate=48.56} ModelPlus{dt=2022-01,num=29.54,basisRate=0, loopRate=-65.53} ModelPlus{dt=2022-02,num=74.51,basisRate=0, loopRate=152.27} ModelPlus{dt=2022-03,num=57.86,basisRate=0, loopRate=-22.35} ModelPlus{dt=2022-04,num=7.75,basisRate=0, loopRate=-86.6} ModelPlus{dt=2022-05,num=87.68,basisRate=0, loopRate=1030.71} ModelPlus{dt=2022-06,num=25.71,basisRate=0, loopRate=-70.68} ModelPlus{dt=2022-07,num=84.05,basisRate=0, loopRate=226.9} ModelPlus{dt=2022-08,num=31.43,basisRate=0, loopRate=-62.61} ModelPlus{dt=2022-09,num=85.92,basisRate=80.24, loopRate=173.38} ModelPlus{dt=2022-10,num=69.99,basisRate=217.74, loopRate=-18.55} ModelPlus{dt=2022-11,num=85.9,basisRate=48.9, loopRate=22.73} ModelPlus{dt=2022-12,num=31.91,basisRate=-62.77, loopRate=-62.86} ModelPlus{dt=2023-01,num=74.53,basisRate=152.34, loopRate=133.59} ModelPlus{dt=2023-02,num=21.13,basisRate=-71.65, loopRate=-71.65}

功能是基本实现了,但是还是有很多的代码,下一步需要把它进行优化。

二、动态生成bean版

有时候,我们不想为了增加两个属性给加一个类,那么这个时候可以利用cglib的动态生成bean功能

对上面的方法进行改造

public class Main { private static final DecimalFormat decimalFormat = new DecimalFormat("#.##"); private final static DateTimeFormatter formats = DateTimeFormatter.ofPattern("yyyy-MM"); private final static Random rand = new Random(); public static void main(String[] args) { List models = build(); Map map = models.stream().collect(Collectors.toMap(Model::getDt, Model::getNum)); List list = models.stream().map(model -> { Map newMap = new HashMap(); String dt = model.getDt(); Double num = model.getNum(); String lastM = getLastMonth(dt); String lastYM = getLastYearMonth(dt); Double lastMV = map.get(lastM); Double lastYMV = map.get(lastYM); newMap.put("basisRate",basisRate(lastYMV,num)); newMap.put("loopRate",basisRate(lastMV,num)); return generateObject(model,newMap); }).collect(Collectors.toList()); for (Object o : list) { System.out.println(JSON.toJSONString(o)); } } public static Object generateObject(Object model,Map newProperties) { DynamicObject dynamicBean = new DynamicObject(); Map


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3