字符串格式JSONPath按括号内字母与数值混合排序的最佳实现方案
实现思路
- 第一步:预解析所有JSONPath为结构化的节点列表
用正则匹配提取所有[xxx]中的内容,每个内容对应一个节点:- 若内容以单/双引号包裹,去掉引号后存为字符串类型节点
- 若内容为纯数字,直接转为整型数值存为数字类型节点
提前解析的好处是避免排序过程中重复解析字符串,性能提升明显,尤其当待排序列表规模较大时。
- 第二步:实现自定义比较逻辑
两个JSONPath做比较时,按顺序逐个比对对应位置的节点:- 若当前位置两个节点都是字符串类型,直接按字母序比较
- 若当前位置两个节点都是数字类型,按数值大小比较
- 若前面所有节点都相等,节点数更少的JSONPath排在前面
Java实现示例
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; public class JsonPathSorter { // 解析单个JSONPath为节点列表 private static List<Comparable<?>> parseJsonPath(String jsonPath) { List<Comparable<?>> nodes = new ArrayList<>(); // 匹配所有[]中的内容 Pattern pattern = Pattern.compile("\\[(.*?)]"); Matcher matcher = pattern.matcher(jsonPath); while (matcher.find()) { String content = matcher.group(1); // 判断是字符串节点还是数字节点 if (content.startsWith("'") || content.startsWith("\"")) { // 去掉前后引号 nodes.add(content.substring(1, content.length() - 1)); } else { // 转成整数,数字范围大的话可以换Long nodes.add(Integer.parseInt(content)); } } return nodes; } public static void main(String[] args) { List<String> jsonPathList = new ArrayList<>(); // 此处填入你的JSONPath列表 jsonPathList.add("\"$['book'][10]['title']\""); jsonPathList.add("\"$['book'][2]['title']\""); jsonPathList.add("\"$['movie']['series'][10]['title']\""); jsonPathList.add("\"$['movie']['series'][2]['title']\""); // 预解析所有JSONPath,存为原字符串和节点列表的映射 Map<String, List<Comparable<?>>> pathNodeMap = jsonPathList.stream() .collect(Collectors.toMap(Function.identity(), JsonPathSorter::parseJsonPath)); // 自定义排序 Collections.sort(jsonPathList, new Comparator<String>() { @Override public int compare(String o1, String o2) { List<Comparable<?>> nodes1 = pathNodeMap.get(o1); List<Comparable<?>> nodes2 = pathNodeMap.get(o2); int minLen = Math.min(nodes1.size(), nodes2.size()); for (int i = 0; i < minLen; i++) { Comparable n1 = nodes1.get(i); Comparable n2 = nodes2.get(i); // 同类型直接比较 if (n1.getClass().equals(n2.getClass())) { int cmp = n1.compareTo(n2); if (cmp != 0) { return cmp; } } else { // 不同类型可自定义排序规则,此处示例数字排在字符串前面 return n1 instanceof Integer ? -1 : 1; } } // 前面节点都相等,短的排前面 return Integer.compare(nodes1.size(), nodes2.size()); } }); // 输出排序结果 jsonPathList.forEach(System.out::println); } }
内容的提问来源于stack exchange,提问作者Chatoyancy
相关产品推荐
相关产品推荐

