【问题标题】:TreeMap Comparator not giving the order expected?TreeMap Comparator 没有给出预期的顺序?
【发布时间】:2016-08-22 10:13:06
【问题描述】:

我正在尝试使用以下格式创建TreeMap

TreeMap<Kenel, List<Dog>> treeMapOfKennelsAndDogs;

每个条目都是一个Kennel 对象,并附有Dogs 列表。我想通过 每个犬舍中最年长的狗来比较每个犬舍并相应地排序。

但是treeMap 的顺序不是我所期望的,似乎当一个犬舍在列表中有一个 size 1 的狗列表时,排序是不正确的。

下面是我查找与每个 Kennel 相关的最古老 Dog 的代码,以及我的比较器逻辑。

@Entity
@Table(name = "KENNEL")
public class Kennel {

    //other fields 

    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true)
    @JoinColumn(name = "KENNEL_ID", referencedColumnName = "ID", updatable = true, insertable = true)
    private List<Dog> dogList;

     public DateTime getOldestDogInList() {
        if (dogList.size() == 0) {
            return null; }

        Dog dog= dogList.get(0);
        for (int i = 1; i < dogList.size(); i++) {
            dog d = dogList.get(i);
            if (d.getCreated().isBefore(dog.getCreated())) {
                dog = d;
            }
        }
        return dog.getCreated();
    }

服务类中的比较器逻辑:

    Comparator<Kennel> oldestDog = new Comparator<Kennel>() {
        @Override
        public int compare(Kennel k1, Kennel k2) {

            int result = k1.getOldestDogInList().compareTo(k2.getOldestDogInList());

            return result;
        }
    };

  TreeMap<Kennel, List<Dog>> treeMapOfKennelsAndDogs = new TreeMap<>(oldestDog);    

代码中是否存在会导致 TreeMap 排序不正确的错误?

【问题讨论】:

  • 如果Kenel 已经包含List&lt;Dog&gt; 成员,为什么还需要TreeMap&lt;Kenel, List&lt;Dog&gt;&gt;?您可以改用TreeSet&lt;Kenel&gt;
  • 实际排序是什么?
  • 拥有比其他人更年轻的狗的狗舍实际上在地图上更早?
  • 这是有道理的,因为当您比较日期时,最早的日期在前。
  • 我不明白你的意思?确定最老的应该排在树形图中的第一位吗?

标签: java list entity comparator treemap


【解决方案1】:
  1. Map&lt;K, V&gt; 键的比较逻辑不应依赖于 V 类。
  2. 插入Map 后是否修改键实例?如果是 - 这是一个问题。平等检查仅在插入*。
  3. 与任何排序图一样,由树形图维护的顺序以​​及是否提供显式比较器都必须与 equals 一致。 (来自 javadoc)

【讨论】:

    【解决方案2】:

    服务类中的比较器逻辑:

    TreeSet 不知道您的服务类。它只知道里面的通用类型。

    第一个解决方案:

    比较器逻辑应位于将在TreeSet 中排序的类中。您应该在 Kennel 类中实现 Comparator 和 ovverade compare 方法。

    第二个解决方案:

    在创建TreeMap时设置Comparator

    TreeMap<Kenel, List<Dog>> treemap = new TreeMap<Kenel, List<Dog>>(new Comparator<Kenel>() {
        public int compare(Kennel k1, Kennel k2) {
            int result = k1.getOldestDogInList().compareTo(k2.getOldestDogInList());
            return result;
        }
    });
    

    相关问题:What is the difference between compare() and compareTo()?

    【讨论】:

    • 我无法更改此 Kennel 类,因为它是遗留代码。这就是我现在采用这种方法的原因?
    • @java123999,制作Adapter pattern:创建扩展Kennel的新类,实现Comparator。如果不执行 Comparator,您的 TreeMap 自动排序将不会成功
    • @java123999,我编辑了我的问题。我添加了动态设置Comparator的解决方案
    猜你喜欢
    • 2018-09-18
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多