java ListMap使用多个或者任意个数的key进行排序
使用JAVA自己的排序方法,有的时候是一个可行的选择。
先从简单的开始说起。
一、少数key的情况
有一个需求:根据 menu_level,sort排序,越小的越前面。
--
下面代码按照升序规则进行!
--
Collections.sort(menuList, new Comparator<Map<String, Object>>() {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
// 进行判断
// compareTo当前面小于后面的时候,返回-1。也就是说如果要倒序,那么只要返回1即可。
int cpLevel=((Integer) o1.get("menu_level")).compareTo((Integer) o2.get("menu_level"));
Integer sort1=(o1.get("sort")==null)?10000:(Integer) o1.get("sort");
Integer sort2=(o2.get("sort")==null)?10000:(Integer) o2.get("sort");
int cpSort=sort1.compareTo(sort2);
if (cpLevel==1) {
return 1;
}
else if(cpLevel==0) {
return cpSort;
}
else {
return -1;
}
//return ;
}
});
---
现在稍微复杂下,后文是3个key的比较。
譬如有数据表books,它们的数据如下:select * from books order by author,price desc,publisher
| 2 | 102 | 生命在于运动 | lml | 1000.00 | 中华出版社 |
| 5 | 103 | 2020年异象 | lml | 90.00 | 福建出版社 |
| 9 | 108 | 以史鉴今 | lml | 90.00 | 西安出版社 |
| 4 | 104 | 奋斗在上海 | lzf | 1000.00 | publzf |
| 8 | 107 | 学习方法论 | lzf | 99.00 | 中天出版社 |
| 7 | 106 | 论自力更生的必要性 | lzf | 99.00 | 秦皇汉武 |
| 3 | 1498591124 | Professional Java for Web Applications | Nicholas S. Williams | 59.99 | John Wiley & Sons |
| 6 | 105 | 21世纪-中国-前进 | 五十 | 83.00 | 附件出版社 |
现在希望通过java排序, 代码如下:
@Override
public List<Map<String, Object>> sortByNKeys() {
String sql = "select author,price,publisher,isbn,title from books";
List<Map<String, Object>> bookList = jdbcTp.queryForList(sql); // 使用java 8的 stream 功能进行排序
// order by author,price desc,publisher
/**
* 升序返回-1,倒序返回1即可 有多个key需要比较的时候(不考虑null或者""的情况),当第n个key返回的是0的时候继续比较,如果不是
* 则根据第n个key的比较值返回需要的结果。 譬如第1个key的比较结果是0,则比骄傲第2个, 假定第二的key的比较结果是-1
* 如果要根据第二个倒序,则返回1;如果要根据第二个升序,则直接发那会-1即可 以此类推
*/ Collections.sort(bookList, new Comparator<Map<String, Object>>() {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
// 进行判断
int cp1 = ((String) o1.get("author")).compareTo((String) o2
.get("author"));
BigDecimal price1 = new BigDecimal(o1.get("price").toString());
BigDecimal price2 = new BigDecimal(o1.get("price").toString());
int cp2 = price1.compareTo(price2); String p1 = o1.get("publisher").toString();
String p2 = o2.get("publisher").toString();
int cp3 = p1.compareTo(p2); if (cp1 == 0) {
if (cp2 == 0) {
if (cp3 == 0) {
return 0;
} else {
return cp3;
}
} else {
return cp2 * -1;
}
} else {
return cp1;
}
// return ;
}
}); return bookList;
}
结果输出如下:
[{
"author": "Nicholas S. Williams",
"price": 59.99,
"publisher": "John Wiley & Sons",
"isbn": "1498591124",
"title": "Professional Java for Web Applications"
}, {
"author": "lml",
"price": 1000.00,
"publisher": "中华出版社",
"isbn": "102",
"title": "生命在于运动"
}, {
"author": "lml",
"price": 90.00,
"publisher": "福建出版社",
"isbn": "103",
"title": "2020年异象"
}, {
"author": "lml",
"price": 90.00,
"publisher": "西安出版社",
"isbn": "108",
"title": "以史鉴今"
}, {
"author": "lzf",
"price": 1000.00,
"publisher": "publzf",
"isbn": "104",
"title": "奋斗在上海"
}, {
"author": "lzf",
"price": 99.00,
"publisher": "中天出版社",
"isbn": "107",
"title": "学习方法论"
}, {
"author": "lzf",
"price": 99.00,
"publisher": "秦皇汉武",
"isbn": "106",
"title": "论自力更生的必要性"
}, {
"author": "五十",
"price": 83.00,
"publisher": "附件出版社",
"isbn": "105",
"title": "21世纪-中国-前进"
}]
注:之所以,有所区别,是因为mysql比较的时候,默认不考虑大小写;而java字符串的CompareTo则是按照unicode编码比较进行的。
二、不定个数key的情况
以上可以应付一些简单的要求,如果有不断变化的,任意个数的key需要比较,那么怎么做?
可以参考的一个终极方案,代码如下:
public void sort() {
String dataJson="[{\r\n" +
" \"author\": \"Nicholas S. Williams\",\r\n" +
" \"price\": 59.99,\r\n" +
" \"publisher\": \"John Wiley & Sons\",\r\n" +
" \"isbn\": \"1498591124\",\r\n" +
" \"title\": \"Professional Java for Web Applications\"\r\n" +
"}, {\r\n" +
" \"author\": \"lml\",\r\n" +
" \"price\": 1000.00,\r\n" +
" \"publisher\": \"中华出版社\",\r\n" +
" \"isbn\": \"102\",\r\n" +
" \"title\": \"生命在于运动\"\r\n" +
"}, {\r\n" +
" \"author\": \"lml\",\r\n" +
" \"price\": 90.00,\r\n" +
" \"publisher\": \"福建出版社\",\r\n" +
" \"isbn\": \"103\",\r\n" +
" \"title\": \"2020年异象\"\r\n" +
"}, {\r\n" +
" \"author\": \"lml\",\r\n" +
" \"price\": 90.00,\r\n" +
" \"publisher\": \"西安出版社\",\r\n" +
" \"isbn\": \"108\",\r\n" +
" \"title\": \"以史鉴今\"\r\n" +
"}, {\r\n" +
" \"author\": \"lzf\",\r\n" +
" \"price\": 1000.00,\r\n" +
" \"publisher\": \"publzf\",\r\n" +
" \"isbn\": \"104\",\r\n" +
" \"title\": \"奋斗在上海\"\r\n" +
"}, {\r\n" +
" \"author\": \"lzf\",\r\n" +
" \"price\": 99.00,\r\n" +
" \"publisher\": \"中天出版社\",\r\n" +
" \"isbn\": \"107\",\r\n" +
" \"title\": \"学习方法论\"\r\n" +
"}, {\r\n" +
" \"author\": \"lzf\",\r\n" +
" \"price\": 99.00,\r\n" +
" \"publisher\": \"秦皇汉武\",\r\n" +
" \"isbn\": \"106\",\r\n" +
" \"title\": \"论自力更生的必要性\"\r\n" +
"}, {\r\n" +
" \"author\": \"五十\",\r\n" +
" \"price\": 83.00,\r\n" +
" \"publisher\": \"附件出版社\",\r\n" +
" \"isbn\": \"105\",\r\n" +
" \"title\": \"21世纪-中国-前进\"\r\n" +
"}]";
List<Map<String, Object>> dataList = JSON.parseObject(dataJson,new TypeReference<List<Map<String,Object>>>(){});
System.out.println(dataList);
List<Map<String,Object>> sortList=new ArrayList<Map<String,Object>>();
Map<String,Object> a1=new HashMap<String,Object>();
a1.put("code", "publisher");
a1.put("sortPosition", 3);
a1.put("sortDirection", "desc");
sortList.add(a1);
Map<String,Object> a2=new HashMap<String,Object>();
a2.put("code", "author");
a2.put("sortPosition", 2);
a2.put("sortDirection", "asc");
sortList.add(a2);
Map<String,Object> a3=new HashMap<String,Object>();
a3.put("code", "price");
a3.put("sortPosition", 1);
a3.put("sortDirection", "desc");
sortList.add(a3);
Map<String,Object> a4=new HashMap<String,Object>();
a4.put("code", "title");
a4.put("sortPosition", 4);
a4.put("sortDirection", "asc");
sortList.add(a4);
Map<String,Object> a5=new HashMap<String,Object>();
a5.put("code", "isbn");
a5.put("sortPosition", 5);
a5.put("sortDirection", "asc");
sortList.add(a5);
Collections.sort(sortList, new Comparator<Map<String, Object>>() {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
// 进行判断
int cp1 = o1.get("sortPosition").toString().compareTo(o2.get("sortPosition").toString());
return cp1;
}
});
int sortSize=sortList.size();
int[] compareResultArr=new int[sortSize];
int[] sortDirectionArr=new int[sortSize];
String[] colArr=new String[sortSize];
for(int i=0;i<sortSize;i++) {
compareResultArr[i]=0;
sortDirectionArr[i]=sortList.get(i).get("sortDirection").equals("asc")?1:-1;
colArr[i]=sortList.get(i).get("code").toString();
}
//排序的时候,必须保证多行在custom_id之后,而单行在custom_id之前,避免数据混乱
Collections.sort(dataList, new Comparator<Map<String, Object>>() {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
// 进行判断
for(int i=0,len=sortSize;i<len;i++) {
Object v1=o1.get(colArr[i]);
Object v2=o2.get(colArr[i]);
if (v1 instanceof String) {
compareResultArr[i]=v1.toString().compareTo(v2.toString());
}
else {
compareResultArr[i]=new BigDecimal(v1.toString()).compareTo(new BigDecimal(v2.toString()));
}
}
for(int i=0,len=sortSize;i<len;i++) {
if (compareResultArr[i]!=0) {
return compareResultArr[i]*sortDirectionArr[i];
}
}
//如果都是一样,则直接返回0
return 0;
}
});
System.out.println(dataList);
}
解决思路也比较简单:
1)使用数组保存每个key的比较值和排序方向值(升序1,降序-1)
2)对比较的结果循环判断,只要有不等于0(相等的)就返回
上面的解决还比较粗暴,可以稍微改进下:
Collections.sort(dataList, new Comparator<Map<String, Object>>() {
@Override
public int compare(Map<String, Object> o1, Map<String, Object> o2) {
// 进行判断
for(int i=0,len=sortSize;i<len;i++) {
Object v1=o1.get(colArr[i]);
Object v2=o2.get(colArr[i]);
if (v1 instanceof String) {
compareResultArr[i]=v1.toString().compareTo(v2.toString());
}
else {
compareResultArr[i]=new BigDecimal(v1.toString()).compareTo(new BigDecimal(v2.toString()));
}
//只要有一个不相等,就可以返回了
if (compareResultArr[i]*sortDirectionArr[i]!=0){
return compareResultArr[i]*sortDirectionArr[i];
}
}//如果都是一样,则直接返回0
return 0;
}
});
注意:
1)以上方案没有考虑更多的类型,都是java的基本包装类
2) 不适合要求高性能的环境。如有需要,应该考虑购买算法,或者是使用其它算法计算
3)如果您的应用排序的数据大概是一万行内,且对时间要求不是特别高,那么可以使用以上方法。
java ListMap使用多个或者任意个数的key进行排序的更多相关文章
- 【算法习题】正整数数组中和为sum的任意个数的组合数
1.递归实现(参考:https://blog.csdn.net/hit_lk/article/details/53967627) public class Test { @org.junit.Test ...
- 如何使用 Java 对 List 中每个对象元素按时间顺序进行排序
如何使用 Java 对 List 中每个对象元素按时间顺序进行排序 Java 实现 import java.text.SimpleDateFormat; import java.util.ArrayL ...
- 任意指定一个key获取该key所处在哪个node节点
需求:任意指定一个key获取该key所处在哪个node节点上. 说明:redis自带的命令可以知道一个key所属的slot,可以知道node master对应哪些slot,但没有key和node的对应 ...
- java读取项目根路径下和任意磁盘位置下的properties文件
1.读取项目根路径下的properties文件比较简单也是比较常见的一种操作. 具体代码如下: package com.xuanen.util; import java.util.Properties ...
- java工具类(七)实现给定任意年份和月份得出天数
Java实现给定任意年份和月份,输出该月有多少天 项目开发过程中,细节性的地方需要判定某年某月多少天,写了个下面的小工具解决了此问题. package weiming.lmapp.utils; pub ...
- java统计指定目录中文件的个数和总的大小
转: 统计指定目录中文件的个数和总的大小 package file; import java.io.File; import java.util.ArrayList; public class Fil ...
- Java获取随机数获取制定范围指定个数不重复的随机数
一.JDK中提供的两种方式 1.Math类中的random()方法public static double random()返回带正号的 double 值,该值大于等于 0.0 且小于 1.0 [0. ...
- JAVA实验--统计文章中单词的个数并排序
分析: 1)要统计单词的个数,就自己的对文章中单词出现的判断的理解来说是:当出现一个非字母的字符的时候,对前面的一部分字符串归结为单词 2)对于最后要判断字母出现的个数这个问题,我认为应该是要用到ma ...
- java统计文本中单词出现的个数
package com.java_Test; import java.io.File; import java.util.HashMap; import java.util.Iterator; imp ...
- Java实现 蓝桥杯 算法训练 约数个数
算法提高 约数个数 时间限制:1.0s 内存限制:512.0MB 输入一个正整数N (1 样例输入 12 样例输出 6 样例说明 12的约数包括:1,2,3,4,6,12.共6个 import jav ...
随机推荐
- [Contract] 监听 MetaMask 网络变化, 账号切换
为什么需要监听网络变化?目前在 MetaMask 中切换网络,网页会自动刷新,但是这一特性后面将停止使用. MetaMask: MetaMask will soon stop reloading pa ...
- WPF 自定义控件入门 可重写的各个方法或属性的意义
本文属于 WPF 自定义控件入门系列博客.本文整理在 WPF 里面,自定义控件,非用户控件时,可以重写基类的许多方法和属性,这些方法和属性的作用和含义.方便让大家了解到自定义控件时,有哪些方法或属性可 ...
- notepad运行python代码的步骤
notepad运行python代码的步骤: 1.用notepad++打开python文件.或者新建文件,保存为.py格式. 2.在菜单栏上面有一个运行,我们点击运行->运行,或者使用快捷键F5. ...
- Oracle、达梦:_ 英文下划线 让LIKE查询失效的解决方案:ESCAPE关键字
oracle/dm:_ 英文下划线让like查询失效的解决方案:ESCAPE关键字 -- 可以查询出带(\)的值 SELECT "f1","f2" FROM & ...
- Oracle【ORA-00600 internal error code arguments [2662]】恢复一例
背景 1.数据库版本:11.2.0.4 2.未开启归档 3.没有备份:无RMAN备份.无DUMP备份 4.数据库redo log全部删除. 解决思路: Oracle 的隐含参数: _allow_res ...
- 《最新出炉》系列入门篇-Python+Playwright自动化测试-45-鼠标操作-下篇
1.简介 鼠标为我们使用电脑提供了很多方便,我们看到的东西就可以将鼠标移动过去进行点击就可以打开或者访问内容,当页面内容过长时,我们也可以使用鼠标滚轮来实现对整个页面内容的查看,其实playwrigh ...
- 如何获取Github Token
登录我们的github账号,点击头像后选择Settings 进入界面之后下拉到左侧菜单的最后,选择Developer settings 进入界面后,选择Personal access tokens-- ...
- three.js教程8-渲染器WebGLRenderer和前端UI界面
1.html的UI交互界面与Canvas画布叠加 需求:把threejs Cavnas画布和HTML元素叠加布局,在canvas上添加按钮,通过按钮点击修改canvas场景. // canvas画布绝 ...
- java调用webservice接口
1.直接AXIS调用远程的webservice 注意:不同版本的Axis相差很大,大家最好以apache网站上的例子为准,这里仅仅用于说明其基本用法. import org.apache.axis.c ...
- 十三、.net core(.NET 6)搭建ElasticSearch(ES)系列之dotnet操作ElasticSearch进行存取的方法
.net core操作ES进行读写数据操作 在Package包项目下,新增NEST包.注意,包版本需要和使用的ES的版本保持一致,可以避免因为不兼容所导致的一些问题.例如我本机使用的ES版本是7.13 ...