angeLog>> itemPriceChangeLogMap = itemPriceChangeLogs.stream().collect(Collectors.groupingBy(
ItemPriceChangeLog::getItemId
));
itemCores.forEach(
itemCore -> {
String itemId = itemCore.getId();
itemCore.setItem(itemMap.get(itemId).get(0));
itemCore.setItemPrice(itemPriceMap.get(itemId).get(0));
itemCore.setItemPriceChangeLogs(itemPriceChangeLogMap.get(itemId));
}
);
Order order = new Order();
order.setItemCores(itemCores);
return order;
}
}
@Data
public class TableField {
String tablename;
String field;
String id;
public TableField(String tablename, String field, String id) {
this.tablename = tablename;
this.field = field;
this.id = id;
}
public static TableField buildFrom(String combined) {
String[] parts = combined.split(":");
if (parts != null && parts.length == 3) {
return new TableField(parts[0], parts[1], parts[2]);
}
throw new IllegalArgumentException(combined);
}
}
package zzz.study.utils;
import org.apache.commons.beanutils.BeanUtils;
import java.util.Map;
public class BeanUtil {
public static <T> T map2Bean(Map map, Class<T> c) {
try {
T t = c.newInstance();
BeanUtils.populate(t, map);
return t;
} catch (Exception ex) {
throw new RuntimeException(ex.getCause());
}
}
}
代码重构
group的实现已经不涉及具体业务。这里重点说下 relate 实现的优化。在实现中看到了 if-elseif-elseif-else 条件分支语句。是否可以做成配置化呢?
做配置化的关键在于:将关联项表达成配置。看看 relate 的前半段,实际上就是一个套路: 匹配某个前缀 – 转换为相应的Bean – 加入相应的对象列表。 后半段,需要根据关键字段(itemCoreId)来构建对象列表的 Map 方便做关联。因此,可以提取相应的配置项: (prefix, beanClass, BeanMap, BeanKeyFunc)。这个配置项抽象成 BizObjects , 整体配置构成 objMapping 对象。 在这个基础上,可以将代码重构如下:
public static Order relate2(Map<String, Map<String,Object>> groupedMaps) {
ObjectMapping objectMapping = new ObjectMapping();
objectMapping = objectMapping.FillFrom(groupedMaps);
List<ItemCore> finalItemCoreList = objectMapping.buildFinalList();
Order order = new Order();
order.setItemCores(finalItemCoreList);
return order;
}
ObjectMapping.java
package zzz.study.algorithm.object;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static zzz.study.utils.BeanUtil.map2Bean;
public class ObjectMapping {
Map<String, BizObjects> objMapping;
public ObjectMapping() {
objMapping = new HashMap<>();
objMapping.put("item", new BizObjects<Item,String>(Item.class, new HashMap<>(), Item::getItemCoreId));
objMapping.put("item_core", new BizObjects<ItemCore,String>(ItemCore.class, new HashMap<>(), ItemCore::getId));
objMapping.put("item_price", new BizObjects<ItemPrice,String>(ItemPrice.class, new HashMap<>(), ItemPrice::getItemId));
objMapping.put("item_price_change_log", new BizObjects<ItemPriceChangeLog,String>(ItemPriceChangeLog.class, new HashMap<>(), ItemPriceChangeLog::getItemId));
}
public ObjectMapping FillFrom(Map<String, Map<String,Object>> groupedMaps) {
groupedMaps.forEach(
(key, mapForKey) -> {
String prefixOfKey = key.split(":")[0];
BizObjects bizObjects = objMapping.get(prefixOfKey);