java.util.TreeSet 不遵守 Set 的无重复合同?
java.util.TreeSet not following Set's no duplication contract?
我以前在这里看到过这个问题,但从那时起我没有得到太多帮助,所以我再次提出我真正的问题。
我想根据对象的所有属性删除重复对象(此处Name, id, CompanyName, Address
)。这是我的代码:
package CollectionDemo;
import java.util.TreeSet;
class Employee implements Comparable<Employee> {
String Name;
int id;
String CompanyName;
String Address;
public Employee(String Name,int id,String CompanyName,String Address) {
this.Name = Name;
this.id = id;
this.CompanyName = CompanyName;
this.Address = Address;
}
@Override
public String toString() {
return "Name : "+this.Name+"\tID : "+this.id+"\tCompanyName : "+this.CompanyName+"\tAddress : "+this.Address;
}
@Override
public int compareTo(Employee obj){
if((this.Name.equals(obj.Name))&&(this.id==obj.id)&&(this.CompanyName.equals(obj.CompanyName))&&(this.Address.equals(obj.Address))) {
return 0;
}
return 1;
}
}
public class DemoTreeset {
public static void main(String[] args) {
TreeSet<Employee> ts = new TreeSet<>();
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
for(Employee e : ts) {
System.out.println(e);
}
}
}
输出:
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 12 CompanyName : Google Address : California
Name : Panda ID : 13 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Infosys Address : India
Name : Panda ID : 13 CompanyName : Google Address : California
我知道 TreeSet
使用 compareTo()
而不是 equals()
来比较对象所以我重写了它,但正如您所看到的输出,它删除了一些重复项,但不是全部。我不明白为什么我会得到这个输出。为什么不删除所有重复项,而只删除其中的几个?
当您实现由 Comparable
接口定义的契约时,您需要尊重契约要求实现的所有方面。部分遵守合同会导致奇怪的行为,就像您在您的案例中所经历的那样。 Comparable
合约的一个明显遗漏是 传递性 。来自Comparable.compareTo(...)
方法的javadoc:
The implementor must also ensure that the relation is transitive:
(x.compareTo(y)>0 && y.compareTo(z)>0)
implies x.compareTo(z)>0
.
您的实现绝对不是可传递的。
你能看看这个吗?
输出:
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 12 CompanyName : Google Address : California
Name : Panda ID : 13 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Infosys Address : India
package algorithms;
import java.util.TreeSet;
class Employee implements Comparable<Employee> {
String Name;
int id;
String CompanyName;
String Address;
public Employee(String Name,int id,String CompanyName,String Address) {
this.Name = Name;
this.id = id;
this.CompanyName = CompanyName;
this.Address = Address;
}
@Override
public String toString() {
return "Name : "+this.Name+"\tID : "+this.id+"\tCompanyName : "+this.CompanyName+"\tAddress : "+this.Address;
}
@Override
public int compareTo(Employee obj){
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (this.equals(obj)) return EQUAL;
int comparison = this.Name.compareTo(obj.Name);
if (comparison != EQUAL) return comparison;
comparison = this.Address.compareTo(obj.Address);
if (comparison != EQUAL) return comparison;
comparison = this.CompanyName.compareTo(obj.CompanyName);
if (comparison != EQUAL) return comparison;
comparison = ((Integer)(this.id)).compareTo(obj.id);
if (comparison != EQUAL) return comparison;
return EQUAL;
}
@Override
public boolean equals(Object aThat) {
if (this == aThat) return true;
if (!(aThat instanceof Employee)) return false;
Employee that = (Employee)aThat;
return
( this.Address.equals(that.Address)) &&
(this.id == that.id) &&
( this.Name.equals(that.Name) ) &&
( this.CompanyName.equals(that.CompanyName) )
;
}
}
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet<Employee> ts = new TreeSet<>();
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
for(Employee e : ts) {
System.out.println(e);
}
}
}
我以前在这里看到过这个问题,但从那时起我没有得到太多帮助,所以我再次提出我真正的问题。
我想根据对象的所有属性删除重复对象(此处Name, id, CompanyName, Address
)。这是我的代码:
package CollectionDemo;
import java.util.TreeSet;
class Employee implements Comparable<Employee> {
String Name;
int id;
String CompanyName;
String Address;
public Employee(String Name,int id,String CompanyName,String Address) {
this.Name = Name;
this.id = id;
this.CompanyName = CompanyName;
this.Address = Address;
}
@Override
public String toString() {
return "Name : "+this.Name+"\tID : "+this.id+"\tCompanyName : "+this.CompanyName+"\tAddress : "+this.Address;
}
@Override
public int compareTo(Employee obj){
if((this.Name.equals(obj.Name))&&(this.id==obj.id)&&(this.CompanyName.equals(obj.CompanyName))&&(this.Address.equals(obj.Address))) {
return 0;
}
return 1;
}
}
public class DemoTreeset {
public static void main(String[] args) {
TreeSet<Employee> ts = new TreeSet<>();
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
for(Employee e : ts) {
System.out.println(e);
}
}
}
输出:
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 12 CompanyName : Google Address : California
Name : Panda ID : 13 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Infosys Address : India
Name : Panda ID : 13 CompanyName : Google Address : California
我知道 TreeSet
使用 compareTo()
而不是 equals()
来比较对象所以我重写了它,但正如您所看到的输出,它删除了一些重复项,但不是全部。我不明白为什么我会得到这个输出。为什么不删除所有重复项,而只删除其中的几个?
当您实现由 Comparable
接口定义的契约时,您需要尊重契约要求实现的所有方面。部分遵守合同会导致奇怪的行为,就像您在您的案例中所经历的那样。 Comparable
合约的一个明显遗漏是 传递性 。来自Comparable.compareTo(...)
方法的javadoc:
The implementor must also ensure that the relation is transitive:
(x.compareTo(y)>0 && y.compareTo(z)>0)
impliesx.compareTo(z)>0
.
您的实现绝对不是可传递的。
你能看看这个吗? 输出:
Name : Panda ID : 11 CompanyName : Google Address : California
Name : Panda ID : 12 CompanyName : Google Address : California
Name : Panda ID : 13 CompanyName : Google Address : California
Name : Panda ID : 11 CompanyName : Infosys Address : India
package algorithms;
import java.util.TreeSet;
class Employee implements Comparable<Employee> {
String Name;
int id;
String CompanyName;
String Address;
public Employee(String Name,int id,String CompanyName,String Address) {
this.Name = Name;
this.id = id;
this.CompanyName = CompanyName;
this.Address = Address;
}
@Override
public String toString() {
return "Name : "+this.Name+"\tID : "+this.id+"\tCompanyName : "+this.CompanyName+"\tAddress : "+this.Address;
}
@Override
public int compareTo(Employee obj){
final int BEFORE = -1;
final int EQUAL = 0;
final int AFTER = 1;
if (this.equals(obj)) return EQUAL;
int comparison = this.Name.compareTo(obj.Name);
if (comparison != EQUAL) return comparison;
comparison = this.Address.compareTo(obj.Address);
if (comparison != EQUAL) return comparison;
comparison = this.CompanyName.compareTo(obj.CompanyName);
if (comparison != EQUAL) return comparison;
comparison = ((Integer)(this.id)).compareTo(obj.id);
if (comparison != EQUAL) return comparison;
return EQUAL;
}
@Override
public boolean equals(Object aThat) {
if (this == aThat) return true;
if (!(aThat instanceof Employee)) return false;
Employee that = (Employee)aThat;
return
( this.Address.equals(that.Address)) &&
(this.id == that.id) &&
( this.Name.equals(that.Name) ) &&
( this.CompanyName.equals(that.CompanyName) )
;
}
}
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet<Employee> ts = new TreeSet<>();
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 12, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 13, "Google", "California"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
ts.add(new Employee("Panda", 11, "Google", "California"));
ts.add(new Employee("Panda", 11, "Infosys", "India"));
for(Employee e : ts) {
System.out.println(e);
}
}
}