簡體   English   中英

使用Comparator時從TreeSet丟失數據

[英]Data lost from TreeSet when using Comparator

我有以下代碼,根據他們的經驗對Employees's排序。

我正在增加2名不同nameexperience員工。 我期待在最后一set將有2名員工,但我只有一名。

我也覆蓋了equalshashcode ,任何人都可以告訴我為什么我只能在集合中獲得一名員工。

測試類

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.junit.Test;

public class SetWithComparator {


    @Test
    public void testComparatorWithSet() {

        Comparator<Employee> comparator =
                (emp1, emp2) -> emp1.getYearOFExp().compareTo(emp2.getYearOFExp());

        Set<Employee> empSet = new TreeSet<>(comparator);

        Employee e1 = new Employee();
        e1.setName("Employee-1");
        e1.setYearOFExp(12f);

        Employee e2 = new Employee();
        e2.setName("Employee-2");
        e2.setYearOFExp(12f);

        empSet.add(e1);
        empSet.add(e2);

    }

}

模型類

class Employee {


    private String name;
    private Float yearOFExp;

    public String getName() {
        return name;
    }

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

    public Float getYearOFExp() {
        return yearOFExp;
    }

    public void setYearOFExp(Float yearOFExp) {
        this.yearOFExp = yearOFExp;
    }

    @Override
    public boolean equals(Object obj) {

        if (obj instanceof Employee) {

            Employee e = (Employee) obj;
            return new EqualsBuilder().append(name, e.getName()).isEquals();
        } else {
            return false;
        }

    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(name).toHashCode();
    }

}

因為比較器與你的equals方法不一致。 請查看比較器的文檔。

當且僅當c.compare(e1,e2)== 0具有與每個e1的e1.equals(e2)相同的布爾值時,比較器c對一組元素S施加的排序被稱為與等於一致。和S中的e2

當使用能夠強加與equals不一致的排序的比較器來排序有序集(或有序映射)時,應該謹慎行事。 假設帶有顯式比較器c的有序集(或有序映射)與從集合S中繪制的元素(或鍵)一起使用。如果由S對S施加的排序與equals不一致,則排序集(或有序映射)將表現得“奇怪”。 特別是有序集(或有序映射)將違反集合(或映射)的一般契約,其以等於的方式定義。

您可以在Comparable的文檔中暗示您遇到的確切行為(盡管您使用比較器):

例如,如果添加兩個鍵a和b使得(!a.equals(b)&& a.compareTo(b)== 0)到不使用顯式比較器的有序集,則第二個add操作返回false (並且有序集的大小不會增加)因為a和b從排序集的角度來看是等價的。

在您的情況下: comparator.compare(e1, e2)0e1.equals(e2)false

對於SortedSetComparator確定哪些元素相同,並且不包含重復項。 如果您不想將具有相同體驗的所有員工視為相同,則必須添加二級訂購:

Comparator<Employee> comparator = Comparator.comparing(Employee::getYearOFExp)
                                            .thenComparing(Employee::getName);

請注意,您必須包含構成員工身份的所有屬性。 在您的示例中,只有名稱,但在現實生活中,您可以擁有更多。 另一方面,如果您有一個確定身份的ID,則不需要檢查其他屬性,事實上, 不應該這樣 ,因為大多數屬性(包括名稱)都可以更改。 這也適用於equalshashCode的實現。

為了警告關於可以假設給予什么的錯誤假設,性別變化是一個真實的生活事實,甚至生日可能會變成虛假的,需要糾正。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM