为什么Java TreeSet拒绝添加具有相同比较键而不是等于键的元素?

问题描述 投票:0回答:1

我正在使用TreeSet保存唯一的员工并按名称排序。但是我得到了奇怪的结果。这是代码:


import java.util.Comparator;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;

class Employee implements Comparable<Employee> {
    private int id;
    private String name;

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    // Two Employees are equal if their IDs are equal
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return id == employee.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    // Compare employees based on their IDs
    @Override
    public int compareTo(Employee employee) {
        return this.getId() - employee.getId();
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public static void main(String[] args) {
        SortedSet<Employee> employees = new TreeSet<>();

        // Providing a Custom Comparator (This comparator compares the employees based on their Name)
        employees = new TreeSet<>(Comparator.comparing(Employee::getName));

        employees.add(new Employee(1010, "Rajeev"));
        employees.add(new Employee(1011, "Rajeev"));
        employees.add(new Employee(1005, "Sachin"));
        employees.add(new Employee(1008, "Chris"));

        System.out.println("\nEmployees (sorted based on the supplied Comparator)");
        System.out.println(employees);
    }
}

这里是输出:

Employees (sorted based on the supplied Comparator)
[Employee{id=1008, name='Chris'}, Employee{id=1010, name='Rajeev'}, Employee{id=1005, name='Sachin'}]

我正在使用openJDK-11.0.1_1_macosx。对象employee.add(new Employee(1011,“ Rajeev”));被拒绝。我以为它拒绝带有重复的employee.id的对象,但不拒绝employee.name。

感谢您的帮助。

java treeset
1个回答
0
投票

来自TreeSets javadoc:

请注意,集合维护的排序(无论是否是显式提供比较器)必须为与等于一致正确实现{@code Set}接口。 (请参见{@code可比的}或{@code比较器}与等于一致。)之所以这样,是因为{@code Set}接口是根据{@code equals}操作定义的,但是{@code TreeSet}实例使用其实例执行所有元素比较{@code compareTo}(或{@code compare})方法,所以两个元素从集合的角度来看,被此方法视为相等等于。集合is的行为是明确定义的,即使其顺序与等式不一致;它只是不能听从{@code Set}界面的一般合同。

名称比较器与Employee的equals实现不一致,因为equals仅检查雇员ID。

© www.soinside.com 2019 - 2024. All rights reserved.