Java中如何对Map<String, Object>内的List<Object>进行排序?
解决Map嵌套列表排序问题
问题背景
我有两个Map<String, Object>结构的数据:
Map<String, Object> map1 = { taxRate={rateType=EXCLUSIVE, rate=0.07}, taxAmount={currencyCode=USD, amount=7.0}, jurisdictionTaxes=[{jurisdictionLevel=State, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=County, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=City, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=District, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}], withholdingJurisdictionTaxes=[] } Map<String, Object> map2 = { taxRate={rateType=EXCLUSIVE, rate=0.07}, taxAmount={currencyCode=USD, amount=7.0}, jurisdictionTaxes=[{jurisdictionLevel=State, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=County, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=City, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=District, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}], withholdingJurisdictionTaxes=[] }
我用以下代码比较这两个Map:
Map<String, Object> flatMap1 = FlatMapUtil.flatten(map1); Map<String, Object> flatMap2 = FlatMapUtil.flatten(map2); MapDifference<String, Object> difference = Maps.difference(flatMap1, flatMap2);
但jurisdictionTaxes对应的对象列表顺序会影响差异计算结果,需要在执行Maps.difference前对该列表排序。之前尝试两种方法均报错:
- 方法一:
Collections.sort(Arrays.asList(leftMap.get("jurisdictionTaxes")));
报错:Required type: List <T> Provided: List <Object>
- 方法二:
Arrays.asList(leftMap.get("jurisdictionTaxes")).sort((s1, s2) -> s1.get("jurisdictionLevel") - s2.get("jurisdictionLevel"));
报错:Cannot resolve method 'get' in 'Object'
附Maps.difference源码:
public static <K, V> MapDifference<K, V> difference(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) { if (left instanceof SortedMap) { SortedMap<K, ? extends V> sortedLeft = (SortedMap)left; return difference(sortedLeft, right); } else { return difference(left, right, Equivalence.equals()); } }
解决方案
报错核心是类型转换缺失:从Map中取出的jurisdictionTaxes是Object类型,无法直接作为泛型列表排序,必须先强转为List<Map<String, Object>>,再指定排序规则。
步骤1:提取并转换列表类型
先从Map中取出目标列表,转换为明确的泛型类型:
// 处理map1的jurisdictionTaxes List<Map<String, Object>> taxesList1 = (List<Map<String, Object>>) map1.get("jurisdictionTaxes"); // 处理map2的jurisdictionTaxes List<Map<String, Object>> taxesList2 = (List<Map<String, Object>>) map2.get("jurisdictionTaxes");
步骤2:对列表排序
根据jurisdictionLevel字段排序,分两种场景:
场景1:按字符串自然排序
直接比较jurisdictionLevel的字符串顺序,同时处理null值避免空指针:
// 对map1的列表排序 taxesList1.sort((taxA, taxB) -> { String levelA = (String) taxA.get("jurisdictionLevel"); String levelB = (String) taxB.get("jurisdictionLevel"); if (levelA == null && levelB == null) return 0; if (levelA == null) return -1; // null放前面 if (levelB == null) return 1; return levelA.compareTo(levelB); }); // 对map2执行相同排序逻辑 taxesList2.sort((taxA, taxB) -> { String levelA = (String) taxA.get("jurisdictionLevel"); String levelB = (String) taxB.get("jurisdictionLevel"); if (levelA == null && levelB == null) return 0; if (levelA == null) return -1; if (levelB == null) return 1; return levelA.compareTo(levelB); });
场景2:按固定层级优先级排序
如果需要State > County > City > District这类固定顺序,先定义优先级映射再排序:
Map<String, Integer> levelPriority = new HashMap<>(); levelPriority.put("State", 1); levelPriority.put("County", 2); levelPriority.put("City", 3); levelPriority.put("District", 4); // 排序逻辑 taxesList1.sort((taxA, taxB) -> { String levelA = (String) taxA.get("jurisdictionLevel"); String levelB = (String) taxB.get("jurisdictionLevel"); int priorityA = levelPriority.getOrDefault(levelA, Integer.MAX_VALUE); int priorityB = levelPriority.getOrDefault(levelB, Integer.MAX_VALUE); return Integer.compare(priorityA, priorityB); });
步骤3:执行差异比较
排序完成后,原列表会被直接修改,无需重新放入Map,直接执行扁平化和差异计算即可:
Map<String, Object> flatMap1 = FlatMapUtil.flatten(map1); Map<String, Object> flatMap2 = FlatMapUtil.flatten(map2); MapDifference<String, Object> difference = Maps.difference(flatMap1, flatMap2);
额外注意
为避免类型转换异常,可先做类型检查:
Object taxesObj = map1.get("jurisdictionTaxes"); if (taxesObj instanceof List) { List<Map<String, Object>> taxesList = (List<Map<String, Object>>) taxesObj; // 排序逻辑 }
内容的提问来源于stack exchange,提问作者Blake
相关产品推荐
相关产品推荐

