java - 将比较器与 Treemap 一起使用会导致键重复
问题描述
我正在使用树图,但创建了自己的比较器,以便树图按值而不是键排序。这很好用,但是每当我覆盖 <key, value> 映射时,都会使用相同的键添加一个新映射,而不是被覆盖(这不应该发生,因为 Java 中的映射意味着具有唯一键)。我什至尝试在添加另一个映射之前先删除映射,但树形图中没有删除任何内容。当我删除比较器时,没有唯一值,并且树形图按预期工作。为什么会这样?
这是我的代码:
public Map<String, List<String>> mapQtToNonSampledCase(List<Entry> cases, Map<String, Integer> populationDistribution) {
Map<String. Integer> distribution = new HashMap<>(populationDistribution);
Map<String. List<String>> qtToCases = new HashMap<>();
Comparator<String> valueComparator = new Comparator<String>() {
public int compare(String k1, String k2) {
int compare = distribution.get(k1).compareTo(distribution.get(k2));
if (compare == 0)
return 1;
else
return compare;
}
};
TreeMap<String, Integer> sortedByValues = new TreeMap<>(valueComparator);
sortedByValues.putAll(distribution);
for(Entry entry: cases) {
List<Map.Entry<String, Integer>> listEntries = sortedByValues.entrySet().stream().collect(Collectors.tolist());
Map.Entry<String, Integer> qt = sortedByValues.firstEntry().getKey().equals(entry.get(UtilsClass.ID).toString()) ? (listEntries.get(1) != null ? listEntries.get(1) : null) : sortedByValues.firstEntry();
if(qt != null) {
if(!qtToCases.containsKey(qt.getKey()) {
qtToCases.put(qt.getKey(), new ArrayList<>());
);
}
qtToCases.get(qt.getKey()).add(entry.get(UtilsClass.ID).toString());
sortedByValues.put(qt.getKey(), qt.getValue() - 1);
}
}
// Printing keys
for(Map.Entry<String, Integer> entry : sortedByValues.entrySet()) {
System.out.println(entry.getKey());
}
}
解决方案
您的自定义比较器与 equals 不一致:当您尝试使用不同的值更新键时,您的比较器将返回一个值!= 0,但键是相同的。
请参阅TreeMap API 文档中的此评论:
请注意,树形映射维护的顺序,就像任何排序映射一样,以及是否提供显式比较器,如果此排序映射要正确实现 Map 接口,则必须与 equals 保持一致。
此处定义了术语“与等于一致”:[Comparable API doc]:2
当且仅当 e1.compareTo(e2) == 0 对于 C 类的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,C 类的自然排序被称为与 equals 一致。
推荐阅读
- c++ - 我的 SWIG 类型图有什么问题?
- c# - C#中抽象工厂设计模式的真实示例
- r - 使用 predict.coxph、simPH 和公式预测相对风险
- android - 上传 APK 并设置发布轨道
- angular - 用于 Angular 自定义 LegendItemComponent 的 kendo-ui
- java - 在 Maven Selenium 项目的 TFS 中找不到 chromedriver 可执行文件
- laravel - 使用两个表的两个不同用户的自定义身份验证。我不想使用 make:auth
- javascript - 在移动浏览器中加载组件时打开 Play 商店
- android - 存储动态数据的最佳方式?
- ruby-on-rails - Rails 关注未定义的方法错误