与HashSet是基于HashMap实现一样,TreeSet同样是基于TreeMap实现的。在大神的Java提高篇(二七)—–TreeMap中详细讲解了TreeMap实现机制。这里只是介绍我的一个错误用法:
import java.util.Set;
import java.util.TreeSet;
/**
* Created by mac on 2017/4/3.
*/
public class TreeSetTest implements Comparable<TreeSetTest> {
int priority;
String name;
public TreeSetTest(int priority, String name) {
this.priority = priority;
this.name = name;
}
@Override
public int compareTo(TreeSetTest o2) {
if (name.equals(o2.name)) {
return 0;
}
if (priority != o2.priority) {
return priority - o2.priority;
}
return -1;
}
public static void main(String args[]) {
Set<TreeSetTest> sets = new TreeSet();
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 10; i++) {
TreeSetTest treeMapTest=new TreeSetTest(0, i + "");
if(!sets.contains(treeMapTest)){
sets.add(treeMapTest);
}
}
System.out.println(sets.size());
}
}
}
输出结果是:
10
18
25
31
34
39
43
47
50
52
这个程序本来是想通过priority排序,但是name作为唯一识别字段,而同一个priority是无序的,结果试验结果与预期不一样。原因在TreeSet的contains()方法的实现上,最后调用了TreeMap的contaninsKey()函数:
public boolean containsKey(Object key) {
return getEntry(key) != null;
}
final Entry<K,V> getEntry(Object key) {
// Offload comparator-based version for sake of performance
if (comparator != null)
return getEntryUsingComparator(key);
if (key == null)
throw new NullPointerException();
@SuppressWarnings("unchecked")
Comparable<? super K> k = (Comparable<? super K>) key;
Entry<K,V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
return null;
}
在这里contanis函数最后根据tree去判断对象是否在存在,当第一个TreeSetTest对象在第一次插入的时候它是最大的那个对象,第二次插入的时候,它和root去比较最后由于name不一致,直接去小的树枝去查找,最后必然找不到。
所以,使用TreeSet和TreeMap的时候,一定要保证数据是唯一有序的。