集合的体系:
—| Collection:单列集合的根接口。
——| List:如果是实现了List接口的集合类,具备的特点: 有序,可重复。
———| ArrayList:底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。
———| LinkedList:底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。
———| Vector(了解即可):底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。
——| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。
———| HashSet:底层是使用了哈希表来支持的,特点: 存取速度快。
———| TreeSet:如果元素具备自然顺序 的特性,那么就按照元素自然顺序的特性进行排序存储。
那现在就来说一说TreeSet。
TreeSet的存储原理:使用红黑树(一种特殊的二叉树)的数据结构进行数据存储,规则:左小右大。逐一比较。
特别注意:二叉树的自动调整。
treeSet添加自定义元素,treeSet要注意的事项:
1) 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。
输出结果:
2) 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在compareTo(T o)方法上。
输出结果:
3)如果比较元素的时候,compareTo方法返回的是0,那么该元素就被视为重复元素,不允许添加。(注意:TreeSet与HashCode、equals方法是没有任何关系。)
输出结果:
4)往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。
import java.util.Set;
import java.util.TreeSet;
import java.util.Comparator;
class Person{ //implements Comparable{
int id;
String name;
int salary;
public Person(){
}
public Person(int id,String name,int salary){
this.id = id;
this.name = name;
this.salary = salary;
}
/*public int compareTo(Object o){ //TreeSet添加自定义元素时,需要实现comparable接口并且重写compareTo方法
Person p = (Person)o;
return this.id-p.id;
}*/
public String toString(){
return this.id+","+this.name+","+this.salary;
}
}
//实现Comparator接口,自定义一个比较器
class MyComparator implements Comparator{
public int compare(Object o1,Object o2){
Person p1 = (Person)o1;
Person p2 = (Person)o2;
return p1.salary - p2.salary;
}
}
public class Demo{
public static void main(String[] args){
MyComparator mc = new MyComparator();
TreeSet ts = new TreeSet(mc);
ts.add(new Person(12,"张三",1000));
ts.add(new Person(11,"李四",2000));
ts.add(new Person(19,"王五",1500));
System.out.println(ts);
ts.add(new Person(12,"田七",3000)); //这里compare的返回值不为0,因为比较的是salary,所以可以添加并且比较
System.out.println(ts);
}
}
输出结果:
5)往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器,那么是以比较器的比较规则优先使用。
输出结果:
如何自定义定义比较器: 自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可。
自定义比较器的格式 :
class 类名 implements Comparator{
}
推荐使用:使用比较器(Comparator),原因:比较器自成一类,随用随调,而comparable接口则只能写在指定的类里面。