Job*_*eph 4 java comparator treeset java-8
我有以下代码,将Employees's根据他们的经验进行排序.
我正在增加2名不同name且相同的员工experience.我期待最终set会有2名员工,但我只有一名员工.
我也覆盖equals和hashcode,任何一个可以告诉我为什么我收到只有一个组的员工.
测试类
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);
}
}
Run Code Online (Sandbox Code Playgroud)
模型类
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();
}
}
Run Code Online (Sandbox Code Playgroud)
因为比较器与你的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)是0,e1.equals(e2)是false.
对于 a SortedSet,Comparator确定哪些元素是相同的,并且不会包含重复项。如果您不想将所有具有相同经验的员工视为相同,则必须添加二级排序:
Comparator<Employee> comparator = Comparator.comparing(Employee::getYearOFExp)
.thenComparing(Employee::getName);
Run Code Online (Sandbox Code Playgroud)
请注意,您必须包括构成员工身份的所有属性。在您的示例中,只有名称,但是,在现实生活场景中,您将拥有更多名称。另一方面,如果您有一个 ID,它决定了身份,则您不需要检查其他属性,事实上,不应该检查,因为大多数属性,包括名称,都可以更改。这也适用于实施equals和hashCode。
为了警告关于可以假定授予什么的错误假设,性别变化是现实生活中的事实,甚至生日也可能被证明是错误的,需要更正。