在许多业务场景中经常遇到并单规则,即根据并单规则中的指定的并单字段对数据进行合并生成,例如其中有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);
});
}
}
测试结果