import java.util.*;
public class UpdateStu implements Comparable {
String name;
long id;
public UpdateStu(String name, long id) {
this.id = id;
this.name = name;
}
public int compareTo(Object o) {
UpdateStu upstu = (UpdateStu) o;
int result = id > upstu.id ? 1 : (id == upstu.id ? 0 : -1);
return result;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void main(String[] args) {
UpdateStu stu1 = new UpdateStu("李同学", 01011);
UpdateStu stu2 = new UpdateStu("陈同学", 01021);
UpdateStu stu3 = new UpdateStu("王同学", 01051);
UpdateStu stu4 = new UpdateStu("马同学", 01012);
TreeSet tree = new TreeSet();
tree.add(stu1);
tree.add(stu2);//这里就有问题了
tree.add(stu3);
tree.add(stu4);
Iterator it = tree.iterator();
System.out.println("Set集合中的所有元素:");
while (it.hasNext()) {
UpdateStu stu = (UpdateStu) it.next();
System.out.println(stu.getId() + " " + stu.getName());
}
it = tree.headSet(stu2).iterator();
System.out.println("截取前面部分的集合:");
while (it.hasNext()) {
UpdateStu stu = (UpdateStu) it.next();
System.out.println(stu.getId() + " " + stu.getName());
}
it = tree.subSet(stu2, stu3).iterator();
System.out.println("截取中间部分的集合");
while (it.hasNext()) {
UpdateStu stu = (UpdateStu) it.next();
System.out.println(stu.getId() + " " + stu.getName());
}
}
}
   我把上述代码implements Comparable 去掉,运行的时候会有错误,为什么
我检查到了是tree.add(stu1);
tree.add(stu2);//这里就有问题了
tree.add(stu3);
tree.add(stu4);
这里有问题的,那位能给我解释一下啊

解决方案 »

  1.   

    TreeSet是用TreeMap来实现的,他是按照一定顺序存放的,这个排序的依据就是所存放元素的compareTo方法,放第一个的时候无需跟任何元素比较,所以不报错,但是从第二个开始就要比较以决定放置的位置了,这时候就要调用compareTo方法,怎么调用compareTo方法呢,只有将类强制转换为Comparable类型之后才能调用啊,但是若你没有实现Comparable接口,那当然就不能强制准换了,所以就报java.lang.ClassCastException
      

  2.   

    首先,让我们来看看JDK中TreeSet类的add方法/**
         * Adds the specified element to this set if it is not already present.
         * More formally, adds the specified element {@code e} to this set if
         * the set contains no element {@code e2} such that
         * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
         * If this set already contains the element, the call leaves the set
         * unchanged and returns {@code false}.
         *
         * @param e element to be added to this set
         * @return {@code true} if this set did not already contain the specified
         *         element
         * @throws ClassCastException if the specified object cannot be compared
         *         with the elements currently in this set
         * @throws NullPointerException if the specified element is null
         *         and this set uses natural ordering, or its comparator
         *         does not permit null elements
         */
        public boolean add(E e) {
    return m.put(e, PRESENT)==null;
        }
    注意抛出的异常~~
    * @throws ClassCastException if the specified object cannot be compared with the elements currently in this set
    也就是说,如果添加的元素不能和已有元素做比较就抛出ClassCastException异常~那两个元素如果判断可比呢?有两种办法,其中一种就是实现 Comparable接口JDK中很多类都实现了Comparable接口,比如Integer至于TreeSet为什么要这样设计,是因为这个类需要实现元素排序的功能那如何实现的排序呢?我们来看 TreeSet的构造方法
     /**
         * Constructs a new, empty tree set, sorted according to the
         * natural ordering of its elements.  All elements inserted into
         * the set must implement the {@link Comparable} interface.
         * Furthermore, all such elements must be <i>mutually
         * comparable</i>: {@code e1.compareTo(e2)} must not throw a
         * {@code ClassCastException} for any elements {@code e1} and
         * {@code e2} in the set.  If the user attempts to add an element
         * to the set that violates this constraint (for example, the user
         * attempts to add a string element to a set whose elements are
         * integers), the {@code add} call will throw a
         * {@code ClassCastException}.
         */
        public TreeSet() {
    this(new TreeMap<E,Object>());
        } /**
         * Constructs a set backed by the specified navigable map.
         */
        TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }
    你可以发现,排序功能实际上是由TreeMap实现的TreeSet的add方法实际上就是调用的的TreeMap的put方法~~最后~看看put方法的源码
    /**
         * Associates the specified value with the specified key in this map.
         * If the map previously contained a mapping for the key, the old
         * value is replaced.
         *
         * @param key key with which the specified value is to be associated
         * @param value value to be associated with the specified key
         *
         * @return the previous value associated with <tt>key</tt>, or
         *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
         *         (A <tt>null</tt> return can also indicate that the map
         *         previously associated <tt>null</tt> with <tt>key</tt>.)
         * @throws ClassCastException if the specified key cannot be compared
         *         with the keys currently in the map
         * @throws NullPointerException if the specified key is null
         *         and this map uses natural ordering, or its comparator
         *         does not permit null keys
         */
        public V put(K key, V value) {
            Entry<K,V> 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<K,V>(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();
                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<K,V>(key, value, parent);
            if (cmp < 0)
                parent.left = e;
            else
                parent.right = e;
            fixAfterInsertion(e);
            size++;
            modCount++;
            return null;
        }
    你可以发现,这个二叉树排序中有一条这样的语句来判断大小cmp = k.compareTo(t.key);这里k,也就是我们TreeSet.add(k) 方法传入的参数更由 Comparable<? super K> k = (Comparable<? super K>) key;可见,插入TreeSet的对象必须实现Compareble接口
      

  3.   


    但是我现在用一个
    import java.util.*;
    public class Text {
    public static void main(String[] args) {
            Set set = new TreeSet();  //HashSet是Set的子接口
            set.add("a");
            set.add("c");
            set.add("A");
            set.add("a"); 
            set.add("C");
            List list = new ArrayList();
            list.add("a");
            list.add("c");
            list.add("A");
            list.add("a"); 
            list.add("C");
            System.out.println(set);
           System.out.println(list);
    }
    }这样添加为又什么没有问题了?
      

  4.   


    你这个添加的是字符串吧,java应该已经帮你实现了比较字符串大小的方法。
    而你添加student类是自定义的,就需要自己实现Comparable 才行。
      

  5.   


    来看看String类的声明
    public final class String
        implements java.io.Serializable, Comparable<String>, CharSequence
    你可以发现String类实际上已经实现了Comparable接口这是String实现的toCompare方法
    /**
         * Compares two strings lexicographically.
         * The comparison is based on the Unicode value of each character in
         * the strings. The character sequence represented by this
         * <code>String</code> object is compared lexicographically to the
         * character sequence represented by the argument string. The result is
         * a negative integer if this <code>String</code> object
         * lexicographically precedes the argument string. The result is a
         * positive integer if this <code>String</code> object lexicographically
         * follows the argument string. The result is zero if the strings
         * are equal; <code>compareTo</code> returns <code>0</code> exactly when
         * the {@link #equals(Object)} method would return <code>true</code>.
         * <p>
         * This is the definition of lexicographic ordering. If two strings are
         * different, then either they have different characters at some index
         * that is a valid index for both strings, or their lengths are different,
         * or both. If they have different characters at one or more index
         * positions, let <i>k</i> be the smallest such index; then the string
         * whose character at position <i>k</i> has the smaller value, as
         * determined by using the &lt; operator, lexicographically precedes the
         * other string. In this case, <code>compareTo</code> returns the
         * difference of the two character values at position <code>k</code> in
         * the two string -- that is, the value:
         * <blockquote><pre>
         * this.charAt(k)-anotherString.charAt(k)
         * </pre></blockquote>
         * If there is no index position at which they differ, then the shorter
         * string lexicographically precedes the longer string. In this case,
         * <code>compareTo</code> returns the difference of the lengths of the
         * strings -- that is, the value:
         * <blockquote><pre>
         * this.length()-anotherString.length()
         * </pre></blockquote>
         *
         * @param   anotherString   the <code>String</code> to be compared.
         * @return  the value <code>0</code> if the argument string is equal to
         *          this string; a value less than <code>0</code> if this string
         *          is lexicographically less than the string argument; and a
         *          value greater than <code>0</code> if this string is
         *          lexicographically greater than the string argument.
         */
        public int compareTo(String anotherString) {
    int len1 = count;
    int len2 = anotherString.count;
    int n = Math.min(len1, len2);
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = offset;
    int j = anotherString.offset; if (i == j) {
        int k = i;
        int lim = n + i;
        while (k < lim) {
    char c1 = v1[k];
    char c2 = v2[k];
    if (c1 != c2) {
        return c1 - c2;
    }
    k++;
        }
    } else {
        while (n-- != 0) {
    char c1 = v1[i++];
    char c2 = v2[j++];
    if (c1 != c2) {
        return c1 - c2;
    }
        }
    }
    return len1 - len2;
        }
      

  6.   

    TreeSet是一个有序的set,它实现了Comparable.用于比较排序。
      

  7.   


    感觉这句话说得有问题code=Java]
    public class TreeSet<E> extends AbstractSet<E>
        implements NavigableSet<E>, Cloneable, java.io.Serializable
    {
    [/code]TreeSet并没有实现Comparable
      

  8.   

    太感谢了,困扰多天的TreeSet添加元素调用put方法的由来,彻底通顺了,十分感谢,层主大神。