并单规则(数据分组)

在许多业务场景中经常遇到并单规则,即根据并单规则中的指定的并单字段对数据进行合并生成,例如其中有5条行数据,并单后可能生成1条单据或者多条单据。具体实现案例代码如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Invoice {
   private Integer id;
   private String name;
   private Integer days;
   private Long supplierId;
   private Long itemId;
}
/**
 * flag字段为1表示参与并单规则,为0则不参与并单
 */
@Data
public class MergeRule {
    private Integer nameFlag = 1;
	private Integer daysFlag = 0;
	private Integer itemIdFlag = 0;
	private Integer supplierIdFlag = 1;
}
@Data
public class InvoiceVO extends Invoice {
   private MergeRule mergeRule;

   public InvoiceVO(Invoice invoice, MergeRule rule) {
      BeanUtil.copyProperties(invoice, this);
      this.mergeRule = rule;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) {
         return true;
      }
      if (o == null || getClass() != o.getClass()) {
         return false;
      }
      InvoiceVO invoiceVO = (InvoiceVO) o;
      return ReflectHelper.returnEquals(this, invoiceVO, this.mergeRule);
   }

   @Override
   public int hashCode() {
      return Objects.hash(ReflectHelper.getFlagTrueValues(this, mergeRule));
   }
}
public class ReflectHelper {

   public static Object[] getFlagTrueValues(Object obj, Object rule) {
      // 获取并单规则字段
      List<String> fieldNames = getFields(rule);

      Object[] values = new Object[fieldNames.size()];
      Class<?> clz2 = obj.getClass();
      int index = 0;
      try {
         for (String name : fieldNames) {
            Field field = getField(clz2, name);
            field.setAccessible(true);
            values[index ++] = field.get(obj);
         }
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
      return values;
   }

   public static boolean returnEquals(Object obj, Object target, Object rule) {
      Class<?> src = obj.getClass();
      Class<?> tar = target.getClass();
      // 获取并单规则字段
      List<String> fieldNames = getFields(rule);
      try {
         for (String name : fieldNames) {
            Field srcField = getField(src, name);
            Field tarField = getField(tar, name);
            srcField.setAccessible(true);
            tarField.setAccessible(true);
            if (!Objects.equals(srcField.get(obj), tarField.get(target))) {
               return false;
            }
         }
      } catch (Exception e) {
         throw new RuntimeException(e);
      }

      return true;
   }

   private static List<String> getFields(Object rule) {
      List<String> fieldNames = new ArrayList<>();
      Class<?> clz = rule.getClass();
      Field[] fields = clz.getDeclaredFields();
      try {
         for (Field field : fields) {
            field.setAccessible(true);
            int flag = (int)field.get(rule);
            if (flag == 1) {
               String fieldName = field.getName().substring(0, field.getName().lastIndexOf("Flag"));
               fieldNames.add(fieldName);
            }
         }
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
      return fieldNames;
   }

   private static Field getField(Class<?> clz, String name) {
      while (clz != null) {
         try {
            return clz.getDeclaredField(name);
         } catch (Exception e) {
            clz = clz.getSuperclass();
         }
      }
      return null;
   }

}

测试代码


/**
 * @author kenewstar
 * @date 2021/9/6
 */
public class TestMerge {

   public static void main(String[] args) {
      MergeRule rule = new MergeRule();

      List<Invoice> list = new ArrayList<>();
      list.add(new Invoice(1, "a", 2, 1L, 1L));
      list.add(new Invoice(2, "b", 3, 1L, 3L));
      list.add(new Invoice(3, "a", 3, 1L, 1L));
      list.add(new Invoice(4, "c", 4, 1L, 2L));
      list.add(new Invoice(5, "c", 5, 2L, 1L));
      list.add(new Invoice(6, "a", 2, 1L, 1L));

      Map<InvoiceVO, List<Invoice>> listMap = list.stream().collect(Collectors.groupingBy(x -> {
         return new InvoiceVO(x, rule);
      }));
      listMap.forEach((k, v) -> {
         System.out.println(v);
      });

   }
}

测试结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值