java算法实践,同时也是一个有用的工具类。
例如:一个学生信息的list,学生的信息由班级、性别、学号等,将list按照班级、性别分类。
只需:
Map map = CollectionTools.classifyList(studentAllList,
"classId","sex");
例如:一个学生信息的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
}
]
}
}