如何使用比较器实现Treemap?

时间:2018-09-01 13:45:27

标签: java comparator treemap

我在此问题中遇到的错误已解决,并写在下面的“答案”部分。

问题在于,TreeMap的以下定义引发了编译器错误,我想知道原因。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
     width="200" height="200" overflow="visible" fill="#000">
  <defs>
    <pattern id="bg_40b043e9944a4239b118e0b938054afb"
         patternUnits="userSpaceOnUse" x="-2010" y="-30" width="4500" height="3000"
         patternTransform="scale(0.0667)">
      <image width="4500" height="3000" xlink:href="https://i.stack.imgur.com/YHz1i.jpg"  />
    </pattern>
  </defs>
  <rect width="100%" height="100%" fill="url(#bg_40b043e9944a4239b118e0b938054afb)" />
</svg>

我不了解此Treemap实现错误的原因。谁能解释一下这里发生的事情吗?

2 个答案:

答案 0 :(得分:7)

compare()需要处理三种情况:小于,大于和等于。当它们相等时,您需要返回0

if (o1.roll == o2.roll) {
    return 0;
}
else if (o1.roll < o2.roll) {
    return -1;
}
else {
    return 1;
}

Integer.compare(int x, int y)可以为您完成所有这一切:

public int compare(Student o1, Student o2) {
    return Integer.compare(o1.roll, o2.roll);
}

在Java 8中,您可以在一行中创建整个比较器:

Map<Integer, Student> map = new TreeMap<>(Comparator.comparingInt(s -> s.roll));

答案 1 :(得分:2)

TL; DR:TreeMap<Integer, Student>的比较器需要比较Integer,而不是Student

TreeMap<Integer, Student>从整数(“键”)到学生对象(“值”)的映射,并按整数对映射进行排序。因此,构造函数不接受Comparator<Student>作为参数。

根据TreeMap<K,V>的文档,以比较器为参数的构造函数声明为

    TreeMap​(Comparator<? super K> comparator)

这意味着比较器必须使用K类型,键的类型或K的某些超类型。在您的情况下,KInteger

由于Integer类已经定义了顺序,即所谓的自然顺序,所以我建议您根本不需要比较器:

    TreeMap<Integer, Student> map = new TreeMap<>();        

如果您想按学生的roll号存储学生,只需将其插入:

        Student me = new Student();
        map.put(me.roll, me);

副作用是地图按roll排序。

PS the answer by John Kugelman中的信息也是正确的,比较器需要处理三种情况。并且推荐Comparator.comparingInt(s -> s.roll)Comparator.comparingInt(Student::getRoll)(如果该类有这样的吸气剂),不仅是为了简洁,甚至是因为它​​不易出错,因此建议使用更多。