向TreeSet中添加元素时,必须要注意以下几点:
- 向TreeSet中添加的元素必须是同一个类的。
- 可以按照添加进集合中的 元素的指定的顺序遍历。像String类、包装类等默认按照从小到大的顺序遍历。
- 当向TreeSet中添加自定义的对象时,有两种排序的方式:自然排序和定制排序。
- 自然排序:要求自定义类实现java.lang.Comparable接口并重写其CompareTo(Object obj)方法。在此方法中,指明按照自定义类的哪个属性进行排序。
- 向TreeSet中添加元素时,首先按照CompareTo()方法比较,一旦返回0,即认为两个对象完全相同。因此,CompareTo()方法中要完整地比较对象的每一个属性。同时,CompareTo()、equals()和hashCode()三者必须保持一致。如例:
自定义一个Person类
public class Person implements Comparable{
private int age;
private String name;
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
@Override
public int compareTo(Object o) {
int i = this.age - p.age;
return i;
}
}
测试类
import java.util.Set;
import java.util.TreeSet;
import org.junit.Test;
public class TestTreeSet {
@Test
public void test() {
Set set = new TreeSet();
set.add(new Person(50, "wu"));
set.add(new Person(11, "zhang"));
set.add(new Person(20, "wang"));
set.add(new Person(15, "zhao"));
Person p1 = new Person(30, "li");
Person p2 = new Person(30, "liu");
set.add(p1);
set.add(p2);
for(Object str : set) {
System.out.println(str);
}
}
}
按照上述代码,往TreeSet里面添加p1和p2两个对象时,只会添加进一个。因为根据Person类的CompareTo()方法,p1和p2对象时一样的,所以只存进去了一个,所以要按照如下代码修改CompareTo()方法。
public int compareTo(Object o) {
if(o instanceof Person) {
Person p = (Person)o;
int i = this.age - p.age;
if(i == 0) {
return this.name.compareTo(p.name);
}else {
return i;
}
}
return 0;
}
这样的话,p1和p2对象就会都被添加进去。
接下来介绍一下TreeSet中的定制排序。在上述例子中,通过修改Person类中的CompareTo方法就可以实现不同的排序方法。如果在特定情况下,不能够修改Person类的代码,就需要用到定制排序。
定制排序的步骤:
- 创建一个实现了Comparator接口的类对象
- 将此对象作为形参传递给TreeSet的构造器中
- 向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象
可参考下面的例子
Customer类
public class Customer {
private Integer age;
private String name;
public Customer(Integer age, String name) {
super();
this.age = age;
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Customer [age=" + age + ", name=" + name + "]";
}
}
单元测试函数如下所示:
@Test
public void test2() {
//1. 创建一个实现了Comparator接口的类对象
Comparator com = new Comparator(){
//向TreeSet中添加Customer类的对象,在此compare()方法中,指明是按照Customer的哪个属性进行排序的
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Customer && o2 instanceof Customer) {
Customer c1 = (Customer)o1;
Customer c2 = (Customer)o2;
int i = c1.getAge().compareTo(c2.getAge());
if(i == 0) {
return c1.getName().compareTo(c2.getName());
}else {
return i;
}
}
return 0;
}
};
//2. 将此对象作为形参传递给TreeSet的构造器中
TreeSet set = new TreeSet(com);
//3. 向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象
set.add(new Customer(20, "A"));
set.add(new Customer(30, "D"));
set.add(new Customer(10, "C"));
set.add(new Customer(20, "G"));
set.add(new Customer(50, "T"));
for(Object str : set) {
System.out.println(str);
}
}
输出结果如下: