使用map操作物件排序,根據物件欄位排序
map是一個由鍵值對資料組成的集合。在某個專案中,前端顯示的資料量不大,於是採用map進行顯示。但是後來才發現,這樣並不是最簡單的處理方式,但是由於一開始沒考慮好,一路坑到底。把對資料庫的操作轉成在map身上,如果只是用於學習,可以借鑑,如果是要在專案中進行操作的話,可能會偏複雜,特別是分頁操作。
現在描述一下我們的需求:
一 :假設一個物件有三個欄位用來儲存三個名稱,現在要進行排序顯示,第三個名詞根據第二個名稱排序,第二個名稱根據第一個名稱排序。
1:從資料取出資料,存放在Map<String, **>中,**是代表物件,這邊用Object代替。key可以根據物件id儲存,注意:key不能重複,否則資料會出現缺漏。
現在前端要顯示,呼叫儲存的map資料,所以我們需要對資料進行排序
public static Map<String, Object> getSortMap() {
Map<String, Object> tempMap = new LinkedHashMap<String, Object>();
List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>(map.entrySet()
Collections.sort(list,new MyComparator()); //排序操作
Iterator<Map.Entry<String, Object>> i = list.iterator();
while (i.hasNext()) {
Map.Entry<String, Object> entry = i.next();
tempMap.put(entry.getKey(),entry.getValue());
}
return tempMap;
}
排序類:
public class MyComparator implements Comparator<Map.Entry<String, Object>> {
/**
* //:根據父級排序,再根據本身的排序值排序
*/
/*@Override
public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {
Object h1=o1.getValue();
Object h2=o2.getValue();
if ((h1.getName1().compareTo(h2.getName2()))>0) {//先根據第一個名稱排序
return 1;
} else if ((h1.getName1().compareTo(h2.getName1()))==0) {
if ((h1.getName2().compareTo(h2.getName2()))>0) {//第一個名稱相同按第二個名稱排序
return 1;
}else if ((h1.getName2().compareTo(h2.getName2()))==0) {
if ((h1.getName3().compareTo(h2.getName3()))==0) {//第二個名稱相同按第三個名稱排序
return 1;
}else if(Integer.parseInt(h1.getDisplayorder())==Integer.parseInt(h2.getDisplayorder())){
return 0;
}else{
return -1;
}
}else{
return 0;
}
} else
return -1;
}
}
二:現在資料在前端可以顯示了,但是呢,點選欄位的時候要根據這個欄位排序。針對不同框架,前端傳過來的資料可能略不同,這邊是傳“欄位名+空格+排序方式(ASC/DESC)”,比如要根據object的id進行排序,點選的時候會傳id desc或者id asc過來。
1:在object穿件一個排序欄位order
現在在controller需要這樣處理
String orderBy=page.getOrder();//框架封裝自動傳輸的資料
object.order=orderBy;//賦值
2:在相同的getSortMap()進行操作
public static Map<String, Object> getSortMap() {
Map<String, Object> tempMap = new LinkedHashMap<String, Object>();
List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>(map.entrySet());//這裡的map是資料庫查找出來的資料
if(StringUtils.isNotEmpty(Object.order)){//欄位排序操作返回
Collections.sort(list,new MyComparator2(getOrder()));//另一個排序介面
}else{//正常顯示的排序返回
Collections.sort(list,new MyComparator());
}
Iterator<Map.Entry<String, Object>> i = list.iterator();
while (i.hasNext()) {
Map.Entry<String, Object> entry = i.next();
tempMap.put(entry.getKey(),entry.getValue());
}
return tempMap;
}
//這邊要根據欄位排序,我們的思路是通過反射遍歷object屬性,如果前端傳過來的屬性名稱跟object欄位名稱一樣,則根據這個欄位進行排序
public class MyComparator2 implements Comparator<Map.Entry<String, Object>> {
private String orderBy;
public Level2Comparator(String orderBy) {
this.orderBy=orderBy;
}
/**
* 列表排序,根據屬性值排序
*/
@Override
public int compare(Entry<String, Object> o1, Entry<String, Object> o2) {
Object h1=o1.getValue();
Object h2=o2.getValue();
if(StringUtils.isNotEmpty(orderBy)){
String[] fileNames=orderBy.split(" ");
String name=fileNames[0];//屬性名稱
String rule=fileNames[1];//規則.升降
Field[] fs = HkCategory.class.getDeclaredFields();
for(int i = 0 ; i < fs.length; i++){
Field f = fs[i];
f.setAccessible(true); //設定些屬性是可以訪問的
String fileName=f.getName();//屬性名稱
try {
if(name.indexOf(".")>0){//特殊欄位處理比如"level1.name"
String name2=name.substring(name.indexOf(".")+1,name.length());
name=name.substring(0, name.indexOf("."));
}
if(fileName.equals(name)){
if("level1".equals(name)||"level2".equals(name)){
LevelCategory level1=null;
LevelCategory level2=null;
if("level1".equals(name)){
level1=h1.getLevel1();
level2=h2.getLevel1();
}
if("level2".equals(name)){
level1=h1.getLevel2();
level2=h2.getLevel2();
}
if((level1.getName().compareTo(level2.getName()))>0){
if("ASC".equals(rule)){
return 1;
}else{
return -1;
}
}else if((level1.getName().compareTo(level2.getName()))==0){
return 0;
}else{
if("ASC".equals(rule)){
return -1;
}else{
return 1;
}
}
}
String UpFirstOrderBy=name.substring(0, 1).toUpperCase();
String UpOrderBy=UpFirstOrderBy+name.substring(1, name.length());
Method m2 = HkCategory.class.getMethod("get"+UpOrderBy);//呼叫get方法
Object obj1=m2.invoke(h1);//獲取屬屬性值
Object obj2=m2.invoke(h2);;//獲取屬屬性值
String fileType = f.getType().getSimpleName().toLowerCase();//得到此屬性的型別
if("integer".equals(fileType)){//srtring,date,integer不同的資料型別,排序操作不一樣
Integer a1=(Integer) obj1;
Integer a2=(Integer) obj2;
if(a1>a2){
if("ASC".equals(rule)){
return 1;
}else{
return -1;
}
}else if(a1==a2){
return 0;
}else{
if("ASC".equals(rule)){
return -1;
}else{
return 1;
}
}
}
if("date".equals(fileType)){
Date date1=(Date) obj1;
Date date2=(Date) obj2;
if(date1.getTime()<date2.getTime()){
if("ASC".equals(rule)){
return 1;
}else{
return -1;
}
}else if(date1.getTime()==date2.getTime()){
return 0;
}else{
if("ASC".equals(rule)){
return -1;
}else{
return 1;
}
}
}
if("string".equals(fileType)){
if("displayorder".equals(fileName)){//數值排序
Integer a1=Integer.parseInt(obj1.toString());
Integer a2=Integer.parseInt(obj2.toString());
if(a1>a2){
if("ASC".equals(rule)){
return 1;
}else{
return -1;
}
}else if(a1==a2){
return 0;
}else{
if("ASC".equals(rule)){
return -1;
}else{
return 1;
}
}
}else{
if((obj1.toString().compareTo(obj2.toString()))>0){
if("ASC".equals(rule)){
return 1;
}else{
return -1;
}
}else if((obj1.toString().compareTo(obj2.toString()))==0){
return 0;
}else{
if("ASC".equals(rule)){
return -1;
}else{
return 1;
}
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return 0;
}
}
綜上:已經完成map的資料顯示,排序操作。如果還有進行分頁,那會繼續麻煩下去,如果是使用資料操作的話,排序可能只要一條sql,所以這個坑就到此為止吧。。。。
希望對你學習map有所幫助。