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吧,请多指教。多谢。

解决方案 »

  1.   

    TreeSet源码里
    public boolean add(E e) {
       return m.put(e, PRESENT)==null;
    }
    有个put方法,请问这个put是定义在哪里啊?
      

  2.   


        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;
                    }
                }
            }
        }
      

  3.   

    import java.util.*;
    public class Drink implements Comparable{
    public String name;

    public int compareTo(Object o){
    return 0;
    }
    public static void main(String[] args){
    Drink one = new Drink();
    Drink two = new Drink();
    one.name = "Coffee";
    two.name = "Tea";
    TreeSet<Drink> set= new TreeSet<Drink>();
    set.add(one);
    set.add(two);
    System.out.println(set.size());//如果compareTo返回0,
    //则size是1;如果返回-1或1,则size为2 Iterator iter = set.iterator();
    while(iter.hasNext()){
    System.out.println(((Drink)iter.next()).name);
    }
    }
    }
    写代码测试了下,虽然很具体的实现过程还不是很清楚,但是也勉强可以理解代码的结果了。
      

  4.   

    Comparable 是比大小
    hashCode equals 才是比较是否重复
      

  5.   

    这里并没有重写hashCode方法,默认hashCode将是不同的。
    但是在上面的实例代码里,comparable返回-1,0,+1,结果都是不同的。说明comparable在这里起作用了。
      

  6.   

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

  7.   

    有道理,带hash的类,都是要使用hashcode的。这里不是带hash的类,并且明确实现了comparable类,自然要使用。不然实现就没有意义了。:)
      

  8.   

    请问这个put是那个类中的方法呢?我找了一下,只找到TreeMap中的一个版本,有点不一样:
    public V put(K key, V value) {
            Entry t = root;
            if (t == null) {
                // TBD:
                // 5045147: (coll) Adding null to an empty TreeSet should
                // throw NullPointerException
                //
                // compare(key, key); // type check
                root = new Entry(key, value, null);
                size = 1;
                modCount++;
                return null;
            }
            int cmp;
            Entry 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();
                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 e = new Entry(key, value, parent);
            if (cmp < 0)
                parent.left = e;
            else
                parent.right = e;
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }
      

  9.   

    TreeSet 默认用的 TreeMap 作为 delegate    public TreeSet() {
    this(new TreeMap<E,Object>());
        }public V put(K key, V value) 是TreeMap的。
      

  10.   


    看下TreeSet的源码注释你会明白不是这样的,是用compareTo方法的,因为它底层是用TreeMap实现的,红黑树。