TreeSet: 可以按照添加对象的指定属性进行排序,也就是说指定属性大家都要有,所以对象不能是不同类造的对象
Set set=new TreeSet();
set.add(123);
set.add(456);
set.add("AA");
set.add(new User("Tom", 12));
这么做会报异常
要求:向TreeSet中添加的数据要求是相同类的对象,不能添加不同类的对象,如果是基本数据类型会进行自动装箱
Set set=new TreeSet();
set.add(34);
set.add(-34);
set.add(43);
set.add(11);
set.add(8);
Iterator iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
输出结果为
-34
8
11
34
43
Integer类型是按照从小到大的顺序输出的,String类型也同理,Sring类的排序如果第一个字符一样,就会让第二个字符排序
添加自定义类对象,如果不指定排序规则直接add,会报异常
两种排序方式:自然排序,定制排序
自然排序:
public class Test{
public static void main(String[] args) {
Set set=new TreeSet();
set.add(new User("Tom", 12));
set.add(new User("Jerry",32 ));
set.add(new User("Jim", 2));
set.add(new User("Mike", 65));
set.add(new User("Jack", 33));
Iterator iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class User implements Comparable{
private String name;
private int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@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;
User other = (User) 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 int compareTo(Object o) {
if(o instanceof User) {
User user=(User)o;
return -this.name.compareTo(user.name);
}else {
throw new RuntimeException("输入的类型不匹配");
}
}
}
输出结果:
Person [name=Tom, age=12]
Person [name=Mike, age=65]
Person [name=Jim, age=2]
Person [name=Jerry, age=32]
Person [name=Jack, age=33]
如果把上面的程序改成:
Set set=new TreeSet();
set.add(new User("Tom", 12));
set.add(new User("Jerry",32 ));
set.add(new User("Jim", 2));
set.add(new User("Mike", 65));
set.add(new User("Jack", 33));
set.add(new User("Jack",56));
输出结果不变,理论上来说两个Jack是不同的,应该都能进行添加
但是按照compareTo发现他们是一样的,是return 0
相同的元素就不能进行添加了
TreeSet判断是否相同的标准不是equals,而是用compareTo去比较,如果返回是0,就认为是一样的,如果我们希望年龄为56的Jack也进行输出,就要用二级排序
@Override
//按照姓名从大到小排列,其次年龄从小到大排列
public int compareTo(Object o) {
if(o instanceof User) {
User user=(User)o;
//return -this.name.compareTo(user.name);
int compare=-this.name.compareTo(user.name);
if(compare!=0) {
return compare;
}else {
//说明姓名一样,就比较年龄
return Integer.compare(this.age, user.age);
}
}else {
throw new RuntimeException("输入的类型不匹配");
}
}
此时的输出结果:
Person [name=Tom, age=12]
Person [name=Mike, age=65]
Person [name=Jim, age=2]
Person [name=Jerry, age=32]
Person [name=Jack, age=33]
Person [name=Jack, age=56]
总结: 自然排序中,比较两个对象是否相同的标准为compareTo是否返回0,不再是equals
返回0说明是相同数据,TreeSet中不能放相同的数据,相同的数据就不能再进行添加
TreeSet和TreeMap采用红黑树的存储结构
特点:有序,查询速度比List快
定制排序:和Comparator有关
new TreeSet有一个带参数的构造器,参数类型为Comparator,如果构造器不带参数就是用自然排序的方式,加参数就是按照参数的方式来排序
public class Test{
public static void main(String[] args) {
Comparator com=new Comparator() {
//按照年龄从小到大排列,年龄一样的就视为重复数据
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof User&&o2 instanceof User) {
User u1=(User)o1;
User u2=(User)o2;
return Integer.compare(u1.getAge(),u2.getAge());
}else {
throw new RuntimeException("输入的数据类型不匹配");
}
}
};
Set set=new TreeSet(com);
set.add(new User("Tom", 12));
set.add(new User("Jerry",32 ));
set.add(new User("Jim", 2));
set.add(new User("Mike", 65));
set.add(new User("Jack", 33));
set.add(new User("Mary", 33));
set.add(new User("Jack",56));
Iterator iterator=set.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
class User {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private String name;
private int age;
public User(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@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;
User other = (User) 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;
}
}
运行结果为:
Person [name=Jim, age=2]
Person [name=Tom, age=12]
Person [name=Jerry, age=32]
Person [name=Jack, age=33]
Person [name=Jack, age=56]
Person [name=Mike, age=65]
如果把Jack和Mary换一个位置,那输出的就是Mary了
如果上面的User实现了自然排序,并且调了含参数的构造器,还是按照Comparator的方法去排列
定制排序中,比较两个对象是否相同的标准为compare是否返回0,不再是equals
TreeSet的比较标准不是equals而是根据compare,compareTo是否返回0