java - JAVA - 按多个值对 Json 数组进行排序,同时保留先前的排序顺序
问题描述
我有这个 json,我希望能够按不同类型的多个字段值对其进行排序,同时保留以前的排序顺序。
{
"code": "1603",
"description": "",
"score": 10,
"max": 100,
"effts": "2021-12-07T00:00:00",
"expDate": "2021-06-21",
"charityMaxCount": 1400000,
"charityUseCount": 938297,
"title": "",
"imageUrl": "",
"status": "INACTIVE"
},
{
"code": "1604",
"description": "",
"score": 10,
"max": 100,
"effts": "2020-12-07T00:00:00",
"expDate": "2021-06-21",
"charityMaxCount": 1400000,
"charityUseCount": 938297,
"title": "",
"imageUrl": "",
"status": "INACTIVE"
},
{
"code": "1600",
"description": "",
"score": 10,
"max": 100,
"effts": "2021-12-07T00:00:00",
"expDate": "2021-06-21",
"charityMaxCount": 1400000,
"charityUseCount": 938297,
"title": "",
"imageUrl": "",
"status": "ACTIVE"
},
{
"code": "1606",
"description": "",
"score": 10,
"max": 100,
"effts": "2022-12-07T00:00:00",
"expDate": "2021-06-21",
"charityMaxCount": 1400000,
"charityUseCount": 938297,
"title": "",
"imageUrl": "",
"status": "ACTIVE"
},
{
"code": "1601",
"description": "",
"score": 10,
"max": 100,
"effts": "2020-12-07T00:00:00",
"expDate": "2021-06-21",
"charityMaxCount": 1400000,
"charityUseCount": 938297,
"title": "",
"imageUrl": "",
"status": "ACTIVE"
}
]
我应该决定对其进行排序的字段是通过另一个 json 给出的:
{
"id": 1,
"field": "status",
"type": "string",
"sortMode": "ASC"
},
{
"id": 2,
"field": "expDate",
"type": "string",
"sortMode": "ASC"
}
]
我设法通过将 json 数组转换为列表Hashmap<String,Object>
并编写了一个自定义比较器来实现这一点。问题是,当我按 ASC 顺序按状态排序时,将ACTIVE条目置于顶部时,我不希望当我选择按另一个字段(例如expDate )对其进行排序时,此顺序会变得混乱。
这是我的代码:
public String sort() throws JsonProcessingException {
List<TreeMap<String, String>> sortOrder = readSortOrder(sortOrderJson);
List<HashMap<String, Object>> payLoad = readPayLoad(payloadJson);
ObjectMapper objectMapper = new ObjectMapper();
if (sortOrder.size() > 1) {
for (TreeMap<String, String> map : sortOrder) {
if (map.get(Constants.SORT_MODE).equals(SortOrder.DSC.toString())) {
payLoad.sort(new MapComparator(map.get(Constants.FIELD)).reversed());
} else {
payLoad.sort(new MapComparator(map.get(Constants.FIELD)));
}
}
}
return objectMapper.writeValueAsString(payLoad);
}
public List<HashMap<String, Object>> readPayLoad(String jsonInput) {
ObjectMapper mapper = new ObjectMapper();
List<HashMap<String, Object>> jsonList = new ArrayList<>();
try {
HashMap[] payLoadDTOS = mapper.readValue(jsonInput, HashMap[].class);
jsonList = Arrays.asList(payLoadDTOS);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonList;
}
public List<TreeMap<String, String>> readSortOrder(String sortOrder) {
final ObjectMapper objectMapper = new ObjectMapper();
List<TreeMap<String, String>> jsonList = new ArrayList<>();
try {
TreeMap[] sortOrderDTOS = objectMapper.readValue(sortOrder, TreeMap[].class);
jsonList = Arrays.asList(sortOrderDTOS);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonList;
}
这作为比较器:
public class MapComparator implements Comparator<Map<String, Object>> {
private final String key;
public MapComparator(String key) {
this.key = key;
}
@Override
public int compare(Map<String, Object> one, Map<String, Object> two) {
Object first = one.get(key);
Object second = two.get(key);
if (first instanceof String && second instanceof String) {
if ((isValidDate((String) first) && isValidDate((String) second))
|| (isValidDateTime((String) first) && isValidDateTime((String) second))) {
return DateTimeComparator.getInstance().compare(first, second);
} else {
return ((String) first).compareTo((String) second);
}
} else if (first instanceof Integer && second instanceof Integer) {
return ((Integer) first).compareTo((Integer) second);
}
return 0;
}
}
我认为我应该在另外两个集合中分别说ACTIVE和INACTIVE并对其进行排序,但是我可以进行分离的字段可能是动态的,并且每次都可能发生变化。我怎样才能在算法上处理这个?
解决方案
在相同值条目上保留现有顺序的排序算法称为stable。在 Java 中,您可以查询 API 是否保证给定的排序函数是稳定的,例如 Arrays.sort。
使用多个键进行排序的典型方法是使用稳定的排序算法以键的相反顺序对条目进行顺序排序。
例如,如果您想先按名字排序,然后按姓氏排序,您将首先按姓氏排序,然后按名字排序。
您还需要确保您使用的数据结构保留了插入顺序,例如 Set 或 Map 可能不会保留该顺序。
推荐阅读
- docker - Docker 构建错误 :: exec: \"/bin/sh\": stat /bin/sh: no such file or directory
- vue.js - vue js表达式中的算术
- acumatica - 仅在输入选择器时(在打开选择器网格之前),如何使所有选择器字段可搜索?
- java - 有没有办法在 RESTful API 中过滤或排序数据?
- git - 如果正在创建/删除分支,则 Teamcity 触发器
- sql-server - me.recordset.requery 使用 Query 作为 RecordSource 时出现错误 3251 失败
- image-processing - 某些图像的顶点错误 - Google Vision API 对象本地化
- python - pyenv install: 3.x BUILD FAILED (Ubuntu 20.04 using python-build 20180424)
- php - 带有 pem 和密钥的 php CURL 请求的路径问题
- python - 循环遍历可迭代对象时停止检查条件