【问题标题】:Using a comparator with Treemap causes duplicate keys将比较器与 Treemap 一起使用会导致键重复
【发布时间】:2021-10-11 06:31:32
【问题描述】:

我正在使用树图,但创建了自己的比较器,以便树图按值而不是键排序。这工作得很好,但是每当我覆盖 映射时,而不是被覆盖,新的映射会添加相同的键(这不应该发生,因为 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());
      }
}

这是控制台输出(为质量道歉,这是来自另一台设备的图片):

【问题讨论】:

    标签: java hashmap comparator treemap


    【解决方案1】:

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

    TreeMap API doc看到这条评论:

    请注意,树形图维护的顺序与任何排序图一样, 并且无论是否提供了明确的比较器,都必须 如果此排序映射要正确实现,则与 equals 一致 地图界面。

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

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

    【讨论】:

    • 我明白了,这个逻辑不能应用于值吗?如果没有,是否有更好的方法来让一些数据结构根据它们的值对条目进行排序(并且由于对这些值进行了更改,因此需要更新)?
    • 此外,是否可以让我的比较器与 equals 保持一致而不去掉它?
    猜你喜欢
    • 2020-08-09
    • 1970-01-01
    • 2020-05-06
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 2014-01-28
    相关资源
    最近更新 更多