java演算法實踐,同時也是一個有用的工具類。
例如:一個學生資訊的list,學生的資訊由班級、性別、學號等,將list按照班級、性別分類。
只需:
Map map = CollectionTools.classifyList(studentAllList,
"classId","sex");
這個工具運用反射可將list中的每一個學生按照classId和sex分類成一個樹狀的map。
package utils; import java.lang.reflect.InvocationTargetException;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import java.util.Map; import org.apache.commons.beanutils.PropertyUtils;/** * * @author klguang * @version 0.1 */public class CollectionTools { /** * 運用PropertyUtils取得bean的值,並根據keyName歸類 * * @param list * List beans * @param keyName * 需要歸類的bean的屬性名稱 * @return LinkedHashMap<String, List>,有順序的map<br> * map的key為需要歸類的bean的屬性名稱+"#"+對應的屬性值:eg:"class#312"<br> * value為List<bean><br> * * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public static LinkedHashMap<String, List> classify(List list, String keyName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { LinkedHashMap<String, List> target = new LinkedHashMap(); for (Object obj : list) { // 取得bean需要歸類的屬性(keyName)的值,不做類型轉換 Object oKeyValue = PropertyUtils.getProperty(obj, keyName); String keyValue = keyName + "#" + String.valueOf(oKeyValue); if (!target.containsKey(keyValue)) { // 如果map中沒有歸類key值,則添加key值和相應的list ArrayList keyList = new ArrayList(); keyList.add(obj); target.put(keyValue, keyList); } else { // 如果有歸類key值,則在相應的list中添加這個bean ArrayList keyList = (ArrayList) target.get(keyValue); keyList.add(obj); } } return target; } /** * * 將歸類的Map<String, List>按照 keyName歸類,並用index控制遞迴。<br> * 因為直接調用沒有意義,這個方法為private, * * @param mocl * map of classified list<br> * 也就是運用方法<br> * LinkedHashMap<String, List> classify(List list, String * keyName)<br> * 將list歸類成的map<br> * * @param index * 用條件 index < keyNames.length控制遞迴 * * @param keyNames * 需要歸類的bean的屬性名稱 * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ private static LinkedHashMap<String, Map> classify(Map<String, List> mocl, int index, String... keyNames) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { // 單步理解:target是函數參數Map<String, List> mocl再次歸類成的LinkedHashMap<String,Map> // 遞迴到最後這個是最終歸類好的map LinkedHashMap<String, Map> target = new LinkedHashMap(); // 控制遞迴條件,起始的index應該總是1。 if (index < keyNames.length) { // swap用來儲存參數index的值,這是最容易出錯的一個地方 // 用它保證:在參數Map<String, List> mocl層面迴圈時用相同的index參數值。 int swap = index; for (Map.Entry<String, List> entry : mocl.entrySet()) { String mocl_key = entry.getKey(); List mocl_list = entry.getValue(); // 將List<bean>再次歸類 LinkedHashMap<String, List> _mocl = classify(mocl_list, keyNames[index]); // 如果index達到了數組的最後一個,一定是List<bean>轉map,遞迴結束 if (index == keyNames.length - 1) { target.put(mocl_key, _mocl); } else { // 將List<bean>轉map得到的_mocl,再次歸類 // _mocm 為map of classified map的簡稱 LinkedHashMap<String, Map> _mocm = classify(_mocl, ++index, keyNames); target.put(mocl_key, _mocm); } index = swap; } } return target; } /** * 將Map<String, List> map按照bean需要歸類的屬性名稱keyName歸類 * * @param map * map of classified list<br> * list歸類成的map * @param keyName * bean需要歸類的屬性名稱 * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public static LinkedHashMap<String, Map> classifyMap(Map<String, List> map, String keyName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { LinkedHashMap<String, Map> target = new LinkedHashMap(); for (Map.Entry<String, List> entry : map.entrySet()) { List map_list = entry.getValue(); String map_key = entry.getKey(); LinkedHashMap<String, List> keyMap = classify(map_list, keyName); target.put(map_key, keyMap); } return target; } /** * 將List<bean> 按照指定的bean的屬性進行歸類,keyNames的先後順序會影響歸類結果。<br> * eg:一個學生列表,按照班級和性別歸類<br> * Map map = CollectionUtils.classifyList(studentList, "classId","sex");<br> * * @param list * List beans * @param keyNames * 數組包含需要歸類的bean的屬性名稱 * @return 歸類的有順序的樹狀map<br> * map的key為需要歸類的bean的屬性名稱+"#"+對應的屬性值:eg:"class#312"<br> * map的值為List或者map * * @throws IllegalAccessException * @throws InvocationTargetException * @throws NoSuchMethodException */ public static LinkedHashMap classifyList(List list, String... keyNames) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { if (keyNames == null || keyNames.length == 0) return null; if (keyNames.length == 1) return classify(list, keyNames[0]); else return classify(classify(list, keyNames[0]), 1, keyNames); }}
package test; import java.lang.reflect.InvocationTargetException;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map; import utils.CollectionTools;import utils.JsonUtil; public class CollectionClassifytest { /** * @param args * @throws NoSuchMethodException * @throws InvocationTargetException * @throws IllegalAccessException */ public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { // TODO Auto-generated method stub List<Student> studentAllList = new ArrayList();// 所以班級的學生 studentAllList.add(new Student("1", "A", 1, "Ⅰ", "北", "1")); studentAllList.add(new Student("2", "C", 1, "Ⅱ", "上", "0")); studentAllList.add(new Student("3", "C", 1, "Ⅰ", "北", "1")); studentAllList.add(new Student("4", "B", 1, "Ⅰ", "廣", "1")); studentAllList.add(new Student("5", "A", 1, "Ⅳ", "廣", "1")); studentAllList.add(new Student("6", "C", 1, "Ⅳ", "上", "0")); studentAllList.add(new Student("7", "A", 1, "Ⅳ", "廣", "0")); studentAllList.add(new Student("8", "B", 1, "Ⅰ", "廣", "0")); studentAllList.add(new Student("8", "D", 1, "Ⅲ", "北", "0")); studentAllList.add(new Student("8", "D", 1, "Ⅲ", "廣", "0")); studentAllList.add(new Student("8", "D", 1, "Ⅲ", "上", "0")); Map map = CollectionTools.classifyList(studentAllList, "classId","sex"); System.out.println(JsonUtil.toJSON(map)); //做對比 //System.out.println(JsonUtil.toJSON(classifyTest(studentAllList))); //Date begin=new Date(); //for (int i = 0; i < 1000000; i++) {// Map map = CollectionUtils.classifyList(studentAllList, "province", "academyId",// "classId", "team", "sex");// System.out.println(JsonUtil.toJSON(map)); //} //Date end=new Date(); //System.out.println(end.getTime()-begin.getTime()); } static Map classifyTest(List<Student> studentAllList) { // 步驟1 Map<String, List> map = new HashMap<String, List>(); Map<String, Object> mapLast = new HashMap<String, Object>(); // for(Student student : studentAllList){ for (Iterator it = studentAllList.iterator(); it.hasNext();) { Student student = (Student) it.next(); if (map.containsKey(student.getClassId())) { // 如果已經存在這個數組,就放在這裡 List studentList = map.get(student.getClassId()); studentList.add(student); } else { List studentList = new ArrayList(); // 重新聲明一個數組list studentList.add(student); map.put(student.getClassId(), studentList); } } // System.out.println(JsonUtil.toJSON(map)); // 步驟2 // 利用 處理1 步驟 分組完的資料 ,按性別 男/女 再次分組 for (Map.Entry<String, List> m : map.entrySet()) { // 按索引值遍曆 Map Map mapList = new HashMap(); // List studentSingle = m.getValue(); // 同一班級的學生,男女 List studentListMen = new ArrayList(); // 聲明一個存放男生的 list List studentListWomen = new ArrayList(); // 聲明一個存放女生的 list for (Iterator it = studentSingle.iterator(); it.hasNext();) {// 遍曆 Student student = (Student) it.next(); if ("0".equals(student.getSex())) { // 男生 studentListMen.add(student); // 男生 } else { studentListWomen.add(student); // 女生 } } mapList.put("女", studentListWomen); mapList.put("男", studentListMen); mapLast.put(m.getKey(), mapList); } return mapLast; }}
package test; /** * @author klguang * */public class Student { private String studentId; // 學號 private String sex; // 性別 0 男 1 女 private int team; private String classId; private String academyId;//學院 private String province; public Student(String studentId, String classId, String sex) { super(); this.studentId = studentId; this.classId = classId; this.sex = sex; } public Student(String studentId, String classId,int team, String sex) { super(); this.studentId = studentId; this.classId = classId; this.team=team; this.sex = sex; } public Student(String studentId, String classId,int team, String academyId,String sex) { super(); this.studentId = studentId; this.classId = classId; this.team=team; this.sex = sex; this.academyId=academyId; } public Student(String studentId, String classId,int team, String academyId,String province,String sex) { super(); this.studentId = studentId; this.classId = classId; this.team=team; this.sex = sex; this.academyId=academyId; this.province=province; } public String getClassId() { return classId; } public void setClassId(String classId) { this.classId = classId; } public String getStudentId() { return studentId; } public void setStudentId(String studentId) { this.studentId = studentId; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public int getTeam() { return team; } public void setTeam(int team) { this.team = team; } public String getAcademyId() { return academyId; } public void setAcademyId(String academyId) { this.academyId = academyId; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } }
package utils; import java.util.Date; import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.SerializeConfig;import com.alibaba.fastjson.serializer.SerializerFeature;import com.alibaba.fastjson.serializer.SimpleDateFormatSerializer; public class JsonUtil { private static SerializeConfig mapping = new SerializeConfig(); private static String dateFormat; static { dateFormat = "yyyy-MM-dd HH:mm:ss"; } public static String toJSON(Object jsonText) { return JSON.toJSONString(jsonText, SerializerFeature.WriteDateUseDateFormat); } public static String toJSON(String dateFormat, Object jsonText) { mapping.put(Date.class, new SimpleDateFormatSerializer(dateFormat)); return JSON.toJSONString(jsonText, mapping); } public static String toRealJSON(Object jsonText){ return JSON.toJSONString(jsonText,SerializerFeature.DisableCircularReferenceDetect); }}
{ "classId#A": { "sex#1": [ { "academyId": "Ⅰ", "classId": "A", "province": "北", "sex": "1", "studentId": "1", "team": 1 }, { "academyId": "Ⅳ", "classId": "A", "province": "廣", "sex": "1", "studentId": "5", "team": 1 } ], "sex#0": [ { "academyId": "Ⅳ", "classId": "A", "province": "廣", "sex": "0", "studentId": "7", "team": 1 } ] }, "classId#C": { "sex#0": [ { "academyId": "Ⅱ", "classId": "C", "province": "上", "sex": "0", "studentId": "2", "team": 1 }, { "academyId": "Ⅳ", "classId": "C", "province": "上", "sex": "0", "studentId": "6", "team": 1 } ], "sex#1": [ { "academyId": "Ⅰ", "classId": "C", "province": "北", "sex": "1", "studentId": "3", "team": 1 } ] }, "classId#B": { "sex#1": [ { "academyId": "Ⅰ", "classId": "B", "province": "廣", "sex": "1", "studentId": "4", "team": 1 } ], "sex#0": [ { "academyId": "Ⅰ", "classId": "B", "province": "廣", "sex": "0", "studentId": "8", "team": 1 } ] }, "classId#D": { "sex#0": [ { "academyId": "Ⅲ", "classId": "D", "province": "北", "sex": "0", "studentId": "8", "team": 1 }, { "academyId": "Ⅲ", "classId": "D", "province": "廣", "sex": "0", "studentId": "8", "team": 1 }, { "academyId": "Ⅲ", "classId": "D", "province": "上", "sex": "0", "studentId": "8", "team": 1 } ] }}