TreeSet集合
TreeSet集合概述
-
可以按照添加对象的指定属性,进行排序。具体排序方式取决于构造方法
-
TreeSet():根据其元素的自然排序进行排序
-
TreeSet(Comparator comparator) :根据指定的比较器进行排序
-
示例
package com.ningxiao.day19;
import java.util.TreeSet;
public class Demo06 {
public static void main(String[] args) {
TreeSet<Integer> it = new TreeSet<>();
it.add(5);
it.add(8);
it.add(28);
it.add(1);
it.add(16);
for (Integer i:it){
System.out.println(i);
}
}
}
分析底层代码:
//我们分析一下integer类型是如何实现自然排序的
//在我们向集合里添加元素的时候,我们使用add()方法
it.add(5);
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
...
public boolean add(E e) {
return m.put(e, PRESENT)==null;
}
...
}
//我们发现add方法里有一个put()方法
//我们点进去:
public interface Map<K,V> {
...
V put(K key, V value);
...
}
//发现put方法在一个接口里,是一个抽象方法
//那么我们现在去TreeSet类里面看一下是否实现了这个接口
//寻找一圈我们发现并没有这个方法,但是我们注意到,在无参构造方法中
//创建里一个TreeMap类的对象:
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
...
public TreeSet() {
this(new TreeMap<E,Object>());
}
...
}
//我们点进去看一下TreeMap类里面是否实现了方法
//我们发现TreeMap里实现了put()方法
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;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
Comparator<? super K> cpr = comparator;
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
else {
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;
modCount++;
return null;
}
//这个时候,我们发现这就是一个根据平衡二叉树进行的比较排序
//那么问题来了,既然compare接口中的compareTo方法是抽象方法
//那么谁实现了这个方法?
cmp = k.compareTo(t.key);
//这个时候我们要引出Integer数据类型
public final class Integer extends Number implements Comparable<Integer> {
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
}
//这个时候,我们发现Integer类里有实现方法,我们发现这个方法
//调用了compare()方法
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
//这个方法说明了,二叉排序的规则,>0返回1,<0返回-1,相等返回0
这个时候我们就总结:
在创建TreeSet集合的时候,我们会对自然数进行排序
因为在我们添加数据的时候,会对自然数进行二叉排序
在二叉排序的时候会对数进行比较,需要用到compareTo()方法
但是因为我们创建的是Integer类型的数据,在Integer类型中
重写了compareTo()方法,所以比较的时候用的是Integer类中重写的compareTo()
(所以在我们自定义数据类型的时候也是在我们自定义的类中重写compareTo方法)
在compareTo方法中有compare方法对其进行比较