Alp*_*dar 19 java equals comparable comparator
我们上课吧Person.人有名字和身高.
Equals和hashCode()仅考虑名称.人是可比的(或者我们为它实施比较,无论哪一个).人员按身高进行比较.
期望两个不同的人可以具有相同高度的情况似乎是合理的,但是例如.TreeSet的行为类似于comapareTo()== 0表示等于,而不仅仅是相同的大小.
为了避免这种情况,如果大小相同,比较可以继续查看其他内容,但是它不能用于检测相同大小的不同对象.
例:
import java.util.Comparator;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
public class Person implements Comparable<Person> {
private final String name;
private int height;
public Person(String name,
int height) {
this.name = name;
this.height = height;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public String getName() {
return name;
}
@Override
public int compareTo(Person o) {
return Integer.compare(height, o.height);
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (!Objects.equals(this.name, other.name)) {
return false;
}
return true;
}
public int hashCode() {
int hash = 5;
hash = 13 * hash + Objects.hashCode(this.name);
return hash;
}
public String toString() {
return "Person{" + name + ", height = " + height + '}';
}
public static class PComparator1 implements Comparator<Person> {
@Override
public int compare(Person o1,
Person o2) {
return o1.compareTo(o2);
}
}
public static class PComparator2 implements Comparator<Person> {
@Override
public int compare(Person o1,
Person o2) {
int r = Integer.compare(o1.height, o2.height);
return r == 0 ? o1.name.compareTo(o2.name) : r;
}
}
public static void test(Set<Person> ps) {
ps.add(new Person("Ann", 150));
ps.add(new Person("Jane", 150));
ps.add(new Person("John", 180));
System.out.println(ps.getClass().getName());
for (Person p : ps) {
System.out.println(" " + p);
}
}
public static void main(String[] args) {
test(new HashSet<Person>());
test(new TreeSet<Person>());
test(new TreeSet<>(new PComparator1()));
test(new TreeSet<>(new PComparator2()));
}
}
Run Code Online (Sandbox Code Playgroud)
结果:
java.util.HashSet
Person{Ann, height = 150}
Person{John, height = 180}
Person{Jane, height = 150}
java.util.TreeSet
Person{Ann, height = 150}
Person{John, height = 180}
java.util.TreeSet
Person{Ann, height = 150}
Person{John, height = 180}
java.util.TreeSet
Person{Ann, height = 150}
Person{Jane, height = 150}
Person{John, height = 180}
Run Code Online (Sandbox Code Playgroud)
你知道为什么会这样吗?
Luk*_*der 17
从java.util.SortedSetjavadoc中提取:
请注意,如果有序集合要正确实现Set接口,则由有序集合维护的排序(无论是否提供显式比较器)必须与equals一致.(有关与equals一致的精确定义,请参阅Comparable接口或Comparator接口.)这是因为Set接口是根据equals操作定义的,但是有序集使用compareTo(或compare)方法执行所有元素比较因此,从排序集的角度来看,这种方法被认为相等的两个元素是相等的.即使排序与equals不一致,排序集的行为也是明确定义的; 它只是不遵守Set接口的一般合同.
因此,换句话说,SortedSet中断(或"扩展")为一般的合同Object.equals()和Comparable.compareTo.查看合同compareTo:
强烈建议,但并非严格要求(x.compareTo(y)== 0)==(x.equals(y)).一般来说,任何实现Comparable接口并且违反此条件的类都应该清楚地表明这一事实.推荐的语言是"注意:此类具有与equals不一致的自然顺序."
nfe*_*ner 10
如果对相同对象的调用将compareTo返回0,则建议仅返回:equalstrue
当且仅当e1.compareTo(e2)== 0与c1的每个e1和e2的e1.equals(e2)具有相同的布尔值时,C类的自然排序被认为与equals一致. null不是任何类的实例,并且即使e.equals(null)返回false,e.compareTo(null)也应抛出NullPointerException.
(来自JDK 1.6 Javadocs)
TreeSet不使用哈希码和相等操作 - 它只在你给它的比较器的基础上运行.请注意,Javadoc声明:
请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致.(有关与equals一致的精确定义,请参阅Comparable或Comparator.)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的.集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同.
在您的情况下,您的比较*与之不一致equals,因此您的集合不遵守一般合同Set.
为什么不在比较中添加更多方面,以便只有相等的元素与0的结果进行比较?
| 归档时间: |
|
| 查看次数: |
14052 次 |
| 最近记录: |