(小工具)Java反射机制实现任意对象集合按指定任意字段进行分组通用程序实践
2017-08-05 16:29
489 查看
在应用开发的时候,我们有时候会遇到需要对一个给定集合进行分组的情况。如果该集合的数据记录是从数据库的获取,通常我们最简单的方案是直接在sql层面select后group by完成。 但是,假如某些场景下该数据不是从数据库获取呢?那就需要在应用程序层面进行分组。
假设给定一个集合,{A:5,A:4,A:3,B:6,B:7}, 需要对其进行分组,使其结果是 {A:[5,4,3],B:[6,7]}。
下面是常规的写法:
上面的例子1)方法就hardcode了List集合里的对象是TspPefScoreCalTotal,这样就使得程序不具有通用性。试试想,下一次是其它数据对象呢?那岂不是重复写上面相似的代码? 还有,2)方法里的分组的关键字随业务变化而调整呢? 那岂不是要改方法里的组合字段?
基于Java设计模式的开放封闭原则。如果要写通用程序,尝试使用java的反射机制,使其可以让调用者输入任意的对象,且可以任意指定按照哪些字段进行分组。下面给出具体实现例子。
当然,上面的程序还没有考虑对于大数据量时候的分组处理是否有性能问题。下回找个时间测试一下。
假设给定一个集合,{A:5,A:4,A:3,B:6,B:7}, 需要对其进行分组,使其结果是 {A:[5,4,3],B:[6,7]}。
下面是常规的写法:
//1)对集合进行分组 public Map<String,List<TspPefScoreCalTotal>> groupListByFields(List<TspPefScoreCalTotal> list){ Map<String,List<TspPefScoreCalTotal>> resultMap = new HashMap<String,List<TspPefScoreCalTotal>>(); String groupKey = null; for(TspPefScoreCalTotal obj : list){ groupKey = formatGroupKeyByFields(obj); if (resultMap.containsKey(groupKey)) { resultMap.get(groupKey).add(obj); } else { List<TspPefScoreCalTotal> pefScoreCalTotalList = new ArrayList<TspPefScoreCalTotal>(); pefScoreCalTotalList.add(obj); resultMap.put(groupKey, pefScoreCalTotalList); } } return resultMap; } //2)构造分组的关键字 private String formatGroupKeyByFields(TspPefScoreCalTotal obj) { return new StringBuilder().append(obj.getBuyerCompanyId()).append("-").append(obj.getOrganizationId()).toString(); }
上面的例子1)方法就hardcode了List集合里的对象是TspPefScoreCalTotal,这样就使得程序不具有通用性。试试想,下一次是其它数据对象呢?那岂不是重复写上面相似的代码? 还有,2)方法里的分组的关键字随业务变化而调整呢? 那岂不是要改方法里的组合字段?
基于Java设计模式的开放封闭原则。如果要写通用程序,尝试使用java的反射机制,使其可以让调用者输入任意的对象,且可以任意指定按照哪些字段进行分组。下面给出具体实现例子。
public class GroupUtil<T> { private String formatGroupKeyByFields(T obj, List<String> fields) { StringBuilder strBu = new StringBuilder(); for(String field : fields){ strBu.append(getFieldValueByName(field,obj)).append("-"); } return strBu.toString(); } public Map<String,List<T>> groupListByFields(List<T> list, Class ObjClazz, List<String> fields){ Map<String,List<T>> resultMap = new HashMap<String,List<T>>(); String groupKey = null; for(T obj : list){ groupKey = formatGroupKeyByFields(obj,fields); if (resultMap.containsKey(groupKey)) { resultMap.get(groupKey).add(obj); } else { List<T> objectList = new ArrayList<T>(); objectList.add(obj); resultMap.put(groupKey, objectList); } } return resultMap; } /** * 根据属性名获取属性值 * */ public Object getFieldValueByName(String fieldName, Object o) { try { String firstLetter = fieldName.substring(0, 1).toUpperCase(); String getter = "get" + firstLetter + fieldName.substring(1); Method method = o.getClass().getMethod(getter, new Class[] {}); Object value = method.invoke(o, new Object[] {}); return value; } catch (Exception e) { e.printStackTrace(); return null; } } /** * @param args */ public static void main(String[] args) { //构造测试例子start GroupUtil<TspPefScoreCalTotal> testGroup = new GroupUtil<TspPefScoreCalTotal>(); TspPefScoreCalTotal t1 = new TspPefScoreCalTotal(); TspPefScoreCalTotal t2 = new TspPefScoreCalTotal(); TspPefScoreCalTotal t3 = new TspPefScoreCalTotal(); TspPefScoreCalTotal t4 = new TspPefScoreCalTotal(); t1.setPefTotalScoreId(1L); t1.setBuyerCompanyId(1L); t1.setOrganizationId(9L); t1.setTotalScore(10L); t2.setPefTotalScoreId(2L); t2.setBuyerCompanyId(2L); t2.setOrganizationId(9L); t2.setTotalScore(5L); t3.setPefTotalScoreId(3L); t3.setBuyerCompanyId(1L); t3.setOrganizationId(9L); t3.setTotalScore(20L); t4.setPefTotalScoreId(4L); t4.setBuyerCompanyId(1L); t4.setOrganizationId(9L); t4.setTotalScore(20L); List<TspPefScoreCalTotal> list = new ArrayList<TspPefScoreCalTotal>(); list.add(t1); list.add(t2); list.add(t3); list.add(t4); //构造测试例子end System.out.println("===================通用分组======================="); List<String> fields = new LinkedList<String>(); fields.add("buyerCompanyId");//指定分组字段 fields.add("organizationId");//指定分组字段 Map<String, List<TspPefScoreCalTotal>> rstMap2 = testGroup.groupListByFields(list,TspPefScoreCalTotal.class,fields); for( Entry<String,List<TspPefScoreCalTotal>> entryTemp : rstMap2.entrySet()){ System.out.println(entryTemp.getKey()); for(TspPefScoreCalTotal obj : entryTemp.getValue()){ System.out.println(testGroup.getFieldValueByName("pefTotalScoreId", obj)); } } } }
public class TspPefScoreCalTotal { private Long pefTotalScoreId; //主键ID private Long totalScore; //得分 private Long totalScoreRanking; //排列名次 private Long buyerCompanyId; //公司 private Long organizationId; //工厂 public Long getPefTotalScoreId() { return this.pefTotalScoreId; } public void setPefTotalScoreId (Long pefTotalScoreId) { this.pefTotalScoreId = pefTotalScoreId; } public Long getTotalScore() { return this.totalScore; } public void setTotalScore (Long totalScore) { this.totalScore = totalScore; } public Long getTotalScoreRanking() { return this.totalScoreRanking; } public void setTotalScoreRanking (Long totalScoreRanking) { this.totalScoreRanking = totalScoreRanking; } public Long getBuyerCompanyId() { return this.buyerCompanyId; } public void setBuyerCompanyId (Long buyerCompanyId) { this.buyerCompanyId = buyerCompanyId; } public Long getOrganizationId() { return this.organizationId; } public void setOrganizationId (Long organizationId) { this.organizationId = organizationId; } }
当然,上面的程序还没有考虑对于大数据量时候的分组处理是否有性能问题。下回找个时间测试一下。
相关文章推荐
- (小工具)Java反射机制实现任意对象集合排序并且获取排列名次的通用程序实践
- 定义一个List集合并实例化对应的实现类对象。循环输入任意个整数,输入0结束输入循环,对集合中的数据进行从大到小的排序后输出
- (小工具)Java分组排序通用程序实践(终结篇)
- C# 使用Dictionary、linq实现根据集合里面的字符串进行分组
- 在水晶报表中实现任意选择指定字段显示(补充)-格线的实现
- 在水晶报表中实现任意选择指定字段显示 (vb.net vs2003)
- [转]在水晶报表中实现任意选择指定字段显示
- (转)逐步为对象集合构建一个通用的按指定属性排序的方法
- 在水晶报表中实现任意选择指定字段显示(Asp.net+c#版)
- DB2字符串按照指定符号进行拆分成多个字段的实现方式
- [转]在水晶报表中实现任意选择指定字段显示
- JavaScript实现为指定对象添加多个事件处理程序的方法
- 通过反射修改指定对象字段值的通用方法
- IOS开发中实现UITableView按照首字母将集合进行检索分组
- List集合按照对象中某个属性排序通用工具类(按对象中某属性排序)
- 在水晶报表中实现任意选择指定字段显示-模板及C#升级版
- 水晶报表中实现任意指定字段显示
- Java:对集合中的对象进行排序需要实现Interface Comparable接口并实现int compareTo(T o)方法
- 拼音字母进行SQL查询指定字段的实现
- 在水晶报表中实现任意选择指定字段显示