使用比较器在 TreeMap 中获取 Null

Getting Null in TreeMap using Comparator

我有一个名为 Empl 的 class 和两个名为 MySalaryCompMyNameComp 的比较器。

当我 运行 这段代码时,我得到 null 作为 MySalaryComp 中的值,如下面的输出所示。

public class Test{

    public static void main(String a[]) {
        TreeMap<Empl, String> tm = new TreeMap<Empl, String>(new MyNameComp());
        tm.put(new Empl("zzz", 3000), "RAM");
        tm.put(new Empl("aaa", 6000), "JOHN");
        Set<Empl> keys = tm.keySet();
        for (Empl key : keys) {
            System.out.println(key + " ==> " + tm.get(key));
        }

        TreeMap<Empl, String> trmap = new TreeMap<Empl, String>(new MySalaryComp());
        trmap.put(new Empl("zzz", 3000), "RAM");
        trmap.put(new Empl("aaa", 6000), "JOHN");
        Set<Empl> ks = trmap.keySet();
        for (Empl key : ks) {
            System.out.println(key + " ==> " + trmap.get(key));
        }
    }
}

class MyNameComp implements Comparator<Empl> {

    @Override
    public int compare(Empl e1, Empl e2) {
        return e1.getName().compareTo(e2.getName());
    }
}

class MySalaryComp implements Comparator<Empl> {

    @Override
    public int compare(Empl e1, Empl e2) {
        if (e1.getSalary() > e2.getSalary()) {
            return 1;
        } else {
            return -1;
        }
    }
}

class Empl {

    private String name;
    private int salary;

    public Empl(String n, int s) {
        this.name = n;
        this.salary = s;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }


}

以上代码的输出是:

Name: aaa-- Salary: 6000 ==> JOHN
Name: zzz-- Salary: 3000 ==> RAM
Name: zzz-- Salary: 3000 ==> null
Name: aaa-- Salary: 6000 ==> null

谁能帮我理解为什么显示空值?以及如何修复它。

您的比较器未正确实现。 阅读 JavaDocs:

https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

试试这个:

@Override
public int compare(Employee e1, Employee e2) {
  return e1.getSalary() - e2.getSalary();
}

为什么需要 return 0?
如果您查看 TreeMap 的源代码,您会看到:

final Entry<K,V> getEntry(Object key) {
  // Offload comparator-based version for sake of performance
  if (comparator != null)
    return getEntryUsingComparator(key);
  if (key == null)
    throw new NullPointerException();
  @SuppressWarnings("unchecked")
  Comparable<? super K> k = (Comparable<? super K>) key;
  Entry<K,V> p = root;
  while (p != null) {
    int cmp = k.compareTo(p.key);
    if (cmp < 0)
      p = p.left;
    else if (cmp > 0)
      p = p.right;
    else
      return p; // <--Here
  }
  return null;
}

如果比较器从不为 0,他将取消引用将为 null 的子分支。

旁注: 你也可以让你的比较器起作用,像这样:

Comparator<Employee> salaryComparator = (e1, e2) -> (e1.getSalary() - e2.getSalary());
TreeMap<Employee, String> trmap = new TreeMap<>(salaryComparator);

因为当两个对象具有相同的薪水时,我的薪水比较器永远不会 return0。

当两个对象的工资相同时,您需要将 MySalaryComp 固定为 return 零。

正确覆盖比较器:您可以使用内置的整数比较器

return Integer.valueOf(e1.getSalary()).compareTo(e2.getSalary());