场景描述

导出Excel,标题没有按照规则排序,如图(红框的展示结果同导出的Excel)
map

排序规则,由数据库给出,根据给定的sortTag进行排序
rule

问题分析:

该集合(keysdata)类型为Map<String,LinkedHashMap<String,List<Object>>>,需要对其中的LinkedHashMap<String,List<Object>>进行排序,而该列的首行并不需要参与排序。该排序相当于用另一个集合的数据对该集合进行排序

思路

  • 首先需要新建一个map集合对象,用于存放生成的数据,为什么不能将生成的数据直接生成于原有集合上?LinkedHashMap只保证顺序,不保证有序,在原有集合上更新数据并不会改变结果顺序(Map特性。虽然结果是有序的)
  • 其次需要一个数组用来判断排序的大小(可以理解为一个辅助数组),这里不能直接使用int,因为lambda不能直接使用外部定义的局部变量,java线程模型中栈帧的私有很可能会导致并发问题。可以使用原子类AtomicInteger进行替换,但不适合该计算场景,也过于复杂了。最后使用数组解决该问题

关键代码实现如下
ruleTag — Map<String, List<Object>> Object指某对象 (ruleTag指图中的sortedTag)
resultData — Map<String,LinkedHashMap<String,List<Object>>> (resultData指图中的keysdata)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 用于接收排序后的数据
LinkedHashMap<String, List<Object>> tempMap = new LinkedHashMap<>();
int[] compareSort = new int[2];

// 对生成的map集合进行排序
resultData.forEach((k, v) -> v.entrySet().stream()
.sorted((o1, o2) -> {
// 初始化
compareSort[0] = 0;
compareSort[1] = 0;
// 按照给定的规则进行排序
ruleTag.get(k).forEach(x -> {
if (o1.getKey().equals(x.getCateName())) {
compareSort[0] = x.getSort();
}
});
ruleTag.get(k).forEach(x -> {
if (o2.getKey().equals(x.getCateName())) {
compareSort[1] = x.getSort();
}
});
return compareSort[0] - compareSort[1] > 0 ? 1 : -1;
})
.forEachOrdered(x -> tempMap.put(x.getKey(), x.getValue())));

结果展示(红框的比较明显,其余数据也进行了排序)
resultMap