java算法实践 将list中的元素按照属性分类成树状的map

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
            }
        ]
    }
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值