日期:2014-05-20  浏览次数:20940 次

SCJP考题求助:TreeSet的add()方法
Java code
Given:
1. public class Drink implements Comparable {
2. public String name;
3. public int compareTo(Object o) {
4. return 0;
5. }
6. }
and:
20. Drink one = new Drink();
21. Drink two = new Drink();
22. one.name= "Coffee";
23. two.name= "Tea";
24. TreeSet set = new TreeSet();
25. set.add(one);
26. set.add(two);


A programmer iterates over the TreeSet and prints the name of each Drink object.
What is the result?
A. Tea
B. Coffee
C. Coffee
Tea
D. Compilation fails.
E. The code runs with no output.
F. An exception is thrown at runtime.


请问:这里的Drink类compareTo()方法返回0,是不是导致set在add时会把除了第一个以外的所有Drink类实例都当作重复对象而不予加入set中。
TreeSet源码里只简单写了:
public boolean add(E e) {
  return m.put(e, PRESENT)==null;
}
不是很懂。

如果compareTo方法返回0,说明两个对象应该是相等的,这种情况下,对于TreeSet来说,是应该按自然顺序排呢,还是直接就当作重复对象不予添加呢。这点是这道题的point吧,请多指教。多谢。

------解决方案--------------------
Java code

    public V put(K key, V value) {
        Entry<K,V> t = root;

        if (t == null) {
            incrementSize();
            root = new Entry<K,V>(key, value, null);
            return null;
       }

        while (true) {
            int cmp = compare(key, t.key);
            if (cmp == 0) {
                return t.setValue(value);
            } else if (cmp < 0) {
                if (t.left != null) {
                    t = t.left;
                } else {
                    incrementSize();
                    t.left = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.left);
                    return null;
                }
            } else { // cmp > 0
                if (t.right != null) {
                    t = t.right;
                } else {
                    incrementSize();
                    t.right = new Entry<K,V>(key, value, t);
                    fixAfterInsertion(t.right);
                    return null;
                }
            }
        }
    }

------解决方案--------------------
hashCode是对于HashSet的,跟这个TreeSet没有任何关系。
你这个Drink类之所以实现了Comparable就是给TreeSet进行比较用的,你的类实现了compareTo方法后就跟自然比较没关系了。TreeSet 实例使用它的 compareTo(或 compare)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。
------解决方案--------------------
TreeSet 默认用的 TreeMap 作为 delegate

public TreeSet() {
this(new TreeMap<E,Object>());
}

public V put(K key, V value) 是TreeMap的。


------解决方案--------------------
探讨
Comparable 是比大小
hashCode equals 才是比较是否重复