第一次写这个有点小激动,hhhhha,最近开发遇到这个需求;
原本是想这样写①,但是不行诶;
随后这样写②,好像可行,但是代码看起来有点不舒服;
强迫症严重,试着写个公共方法去调用。
(11.18更新了多重排序版本)
//方式一
List<Map<String, Object>> sortList = list1.stream()
.sorted(Comparator.comparing(x -> x.get("id")).reversed())
.collect(Collectors.toList());
//方式二
List<Map<String, Object>> sortList = list1.stream()
.sorted((o1, o2) -> Integer.compare(
Integer.parseInt(o1.get("id").toString()),
Integer.parseInt(o2.get("id").toString()))
).collect(Collectors.toList());
应该会有点局限性,各位根据自己的需求完善,考虑是int类型单独做比较,其他类型按字符串比较。
package com.sinoyd.util.utilsstream;
import java.math.BigDecimal;
import java.text.Collator;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 作者:xxx
* 创建时间:2019/10/22 9:14
* 版本:1.0
* 描述:排序扩展类
*/
public class SortUtil {
private static final Comparator<Object> CHINA_COMPARE = Collator.getInstance(Locale.CHINA);
/**
* map类型的集合排序,集合顺序中m1实则在m2之后,多重排序
*
* @param list 集合
* @param sortBy 排序的key值,如a+b-
*/
public static void listSort(List<Map> list, String sortBy) {
LinkedHashMap<String, Boolean> sort = getSortBy(sortBy);
list.sort((m1, m2) -> {
int compare = 0;
for (Map.Entry<String, Boolean> entry : sort.entrySet()) {
String key = entry.getKey();
if (entry.getValue()) {//是否倒序
compare = compare(m2.get(key), m1.get(key), -1, 1);
} else
compare = compare(m1.get(key), m2.get(key), 1, -1);
if (compare != 0) {
return compare;
}
}
return compare;
});
}
/**
* map类型的集合排序,集合顺序中m1实则在m2之后,只能单key值排序
*
* @param list 集合
* @param key 排序的key值
* @param isDesc 是否倒序
*/
public static void listSort(List<Map> list, Object key, boolean isDesc) {
if (isDesc)
list.sort((m1, m2) -> compare(m2.get(key), m1.get(key), -1, 1));//倒序
else
list.sort((m1, m2) -> compare(m1.get(key), m2.get(key), 1, -1));//正序
}
/**
* 处理排序机制
*
* @param sort 排序字符串 如a+b-
*/
private static LinkedHashMap<String, Boolean> getSortBy(String sort) {
String pattern = "[^+-][a-zA-z_]+[+-]*";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(sort);
LinkedHashMap<String, Boolean> map = new LinkedHashMap<>();
while (m.find()) {
String group = m.group();
map.put(group.replace("+", "").replace("-", "").trim(), group.contains("-"));
}
return map;
}
/**
* 当比较结果大于0位置不变,小于0位置互换,等于0似乎是比较其他东西
* 当两个比较值为都为空时,不改变所有空值的添加顺序 = 1
*
* @param r1 当o1为空时.是否交换位置;1不交换-1交换
* @param r2 当o2为空时.是否交换位置;1不交换-1交换
*/
private static int compare(Object o1, Object o2, int r1, int r2) {
if (o1 == null && o2 == null) {
return 1;
} else if (o2 == null) {
return r2;
} else if (o1 == null) {
return r1;
} else {
String s1 = o1.toString();
String s2 = o2.toString();
if (o1 instanceof Number && o2 instanceof Number) {
return new BigDecimal(s1).compareTo(new BigDecimal(s2));
}
return CHINA_COMPARE.compare(s1, s2);
}
}
}
上面的代码直接复制就好了,那开始测试吧
public static void main(String[] args) {
List<Map> list = new ArrayList<>();
list.add(build(1.15, "额"));
list.add(build(1.24, "3.54"));
list.add(build(1.24, "9.11"));
list.add(build(null, "9.12"));
list.add(build(-2.54, "啊"));
list.add(build(2.22, "出"));
list.add(build(2.22, "的"));
list.add(build(-4.11, "个"));
list.add(build(4.12, "2"));
list.add(build(4.11, "1"));
// SortUtil.listSort(list, "bb", true);
SortUtil.listSort(list, "aa-bb-");
System.out.println("aa顺序" + " " + "bb顺序");
list.forEach(x -> {
System.out.print(x.get("aa"));
System.out.print(" ");
System.out.print(x.get("bb"));
System.out.println("");
});
}
private static Map<String, Object> build(Number a, String b) {
Map<String, Object> map = new HashMap<>();
map.put("aa", a);
map.put("bb", b);
return map;
}
emmmm,这样子还可以,考虑是将null一直放在最后面。希望对各位有所帮助,以上!
aa顺序 bb顺序
4.12 2
4.11 1
2.22 的
2.22 出
1.24 9.11
1.24 3.54
1.15 额
-2.54 啊
-4.11 个
null 9.12
后记,发现了点问题 已修改,另外如果key值基本变动少建议用定制dto去代替map来使用,再基于stream的Comparator类来实现排序,更可支持多排序。