java - Java 按某些键的值对映射进行排序
问题描述
如何实现Comparator
按某些键值对地图列表进行排序?我的目标是任意排序两个列表,以便我可以比较不属于排序的其他字段。
例如,假设我有这两个地图列表,我想按名字和姓氏排序。
+-----------+--------+-------+-------+
| List 1 | Map 1 | Map 2 | Map 3 |
+-----------+--------+-------+-------+
| firstName | John | Eric | John |
| lastName | Miller | Smith | Davis |
| age | 17 | 19 | 35 |
+-----------+--------+-------+-------+
+-----------+--------+-------+-------+
| List 2 | Map 1 | Map 2 | Map 3 |
+-----------+--------+-------+-------+
| firstName | Eric | John | John |
| lastName | Smith | Davis | Miller|
| age | 53 | 38 | 26 |
+-----------+--------+-------+-------+
在我对它进行排序之后,现在我可以将 List 1 的 Map 1 与 List 2 的 Map 2 进行比较,看看有什么不同。
所以我有一个实现比较器的类,如下所示:
// Note that the values may not implement Comparable
public class PersonComparator implements Comparator<Map<String, Object>> {
private List<String> sortKeys = Arrays.asList("firstName", "lastName");
@Override
public int compare(Map<String, Object> map1, Map<String, Object> map2) {
Map<String, Object> keyValue1 = new HashMap<>();
sortKeys.forEach(key -> keyValue1.put(key, map1.get(key)));
Map<String, Object> keyValue2 = new HashMap<>();
sortKeys.forEach(key -> keyValue2.put(key, map2.get(key)));
return keyValue2.hashCode() - keyValue1.hashCode();
}
}
调用sort
每个列表将导致以下结果:
+-----------+--------+-------+-------+
| List 1 | Map 1 | Map 2 | Map 3 |
+-----------+--------+-------+-------+
| firstName | John | Eric | John |
| lastName | Miller | Smith | Davis |
| age | 17 | 19 | 35 |
+-----------+--------+-------+-------+
+-----------+--------+-------+-------+
| List 2 | Map 1 | Map 2 | Map 3 |
+-----------+--------+-------+-------+
| firstName | John | Eric | John |
| lastName | Miller | Smith | Davis |
| age | 26 | 53 | 38 |
+-----------+--------+-------+-------+
但是列表的顺序永远不会改变......我做错了什么?
解决方案
最终,您的排序是基于键的哈希码 - 不一定与它们的值相关的排序(即,“较小的”字符串可以有更大的哈希码,反之亦然)。
相反,您应该根据值本身进行排序,即使这意味着将Object
您必须的值显式转换为可比较值:
Comparator<Map<String, Object>> personComparator =
Comparator.comparing(m -> (String) m.get("firstName"))
.thenComparing(m -> (String) m.get("lastName"));
推荐阅读
- opencv - 压力到图像和图像到压力的转换
- spring - 批量插入spring jdbc模板识别失败记录
- javascript - 向表中添加行会更改选择索引?
- c++ - 如何为具有特定名称(QWidget 名称)的 QWidget 的(非直接)子代 QLabel 指定样式?
- c# - 使用 OAuth 2 通过 SMTP 发送邮件
- java - 获取 Mockito 异常:检查的异常对此方法无效
- actions-on-google - 触发 Google Home 设备说话
- python - LIhgtbgm 在二元目标下产生非二元预测?
- azure-sql-database - Azure 数据库中可以拥有的行数的推荐做法
- asp.net-core - 在线发布 .net core 2.2 应用并进行配置