set特点:无序,唯一
查询速度线性表<树<哈希表
HashSet
- 采用Hashtable哈希表存储结构(神奇的结构)
- 优点:添加速度快查询速度快删除速度快
- 缺点:无序
LinkedHashSet
- 采用哈希表存储结构,同时使用链表维护次序
- 有序(添加顺序)
hashtable不是基于内容比较的,而是基于计算的,可以直接计算到存储的地址并访问
TreeSet
- 采用二叉树(红黑树)的存储结构
- 优点:有序(大小顺序)查询速度比List快(按照内容查询)
- 缺点:查询速度没有HashSet快
二叉排序树:左子树<根<右子树
二叉平衡树:首先是排序树,左右子树高度差不超过1
存储规则为红黑树(二叉平衡树的一种,原理???)。
遍历时为中序遍历。中序遍历先找到根节点,比较大小,小则,在找到左子树的根节点比较,大则找到右子树的根节点比较,一层一层下去剪枝。
添加时会进行排序,需要实现Comparable或者Comparator,三步走。TreeSet和TreeMap有关系,最终是TreeMap代码抛出异常,TreeSet底 层调用的是TreeMap。
是否存在外部比较器,存在则使用外部比较器,否则使用内部比较器
private transient NavigableMap<E,Object> m;
private static final Object PRESENT = new Object();
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
}
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
/*
public V put(K key, V value) {
Entry<K,V> t = root;
if (t == null) {
compare(key, key); // type (and possibly null) check
root = new Entry<>(key, value, null);
size = 1;
modCount++;
return null;
}
}
//是否存在外部比较器,存在则使用外部比较器,否则使用内部比较器
final int compare(Object k1, Object k2) {
return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
: comparator.compare((K)k1, (K)k2);
}
*/
实现内部比较器
直接在对象的类实现compareable接口,重写compareTo方法,按分数排序,分数相同则使用姓名排序(字符串重写的compareTo方法),实现内部比较器,只能有一种比较规则,即最常用规则。
//内部比较器
@Override
public int compareTo(Student o) {
if (this.score>o.score){
return 1;
}else if (this.score<o.score){
return -1;
}else {
return this.name.compareTo(o.name);
}
}
this指向当前类,o指向set的前一个类。
实现外部比较器
外部比较器可以指定多个规则类,需要哪个就调哪个,内部比较器则只能有一种。可以创建新的外部类实现Comparator接口,一个外部类就是一个外部比较器,要用时直接new外部类,然后作为TreeSet构造方法的参数。只在当前类使用时可以考虑匿名内部类,直接实现Comparator接口。
Set<Student> set1=new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
double result=o1.getScore()-o2.getScore();
if (result>0){
return 1;
}else if (result<0){
return -1;
}else {
return o1.getSno()-o2.getSno();
}
}
});
set的遍历
- for-each
- Iterator
- 不能使用for循环, 因为没有get(i)
set与list区别
set相比Collection并没有增加方法
但是List相比Collection增加了一些和索引相关的方法
- add(i, elem)
- remove (i)
- set(i. elem)
- get(i)
注意
1.如果将元素放入到HashSet、LinkedHashSet 等底层结构是哈希表的集合中,必须重写两个方法hashCode ()和equals ( ),不然会出现数据重复
2.如果将元素放入到底层结构是二叉排序树的集合中,比如TreeSet,必须实现两个接口中的一个Comparable或者Comparator,不然存储自定义对象会出现异常