首页 > 解决方案 > 将比较器与 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());
      }
}

这是控制台输出(为质量道歉,这是来自另一台设备的图片): 在此处输入图像描述

标签: javahashmapcomparatortreemap

解决方案


您的自定义比较器与 equals 不一致:当您尝试使用不同的值更新键时,您的比较器将返回一个值!= 0,但键是相同的。

请参阅TreeMap API 文档中的此评论:

请注意,树形映射维护的顺序,就像任何排序映射一样,以及是否提供显式比较器,如果此排序映射要正确实现 Map 接口,则必须与 equals 保持一致。

此处定义了术语“与等于一致”:[Comparable API doc]:2

当且仅当 e1.compareTo(e2) == 0 对于 C 类的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,C 类的自然排序被称为与 equals 一致。


推荐阅读