• 中文
    • English
  • 注册
  • 查看作者
  • 关于Java中compareTo方法的一些问题

    今天基友在学习集合类的时候,问了一些关于compareTo方法的问题,整理如下:

    首先我们看代码:

    package tv.zhangjia.tv;
    
    
    import java.util.*;
    
    public class Student implements Comparable <Student> {
    	String name;
    	int age;
    	
    	public Student(int age, String name) {
    		this.name = name;
    		this.age = age;
    	}
    	public int compareTo(Student a){
    		if(this.age < a.age) {
    			return -1;
    		} else if(this.age > a.age) {
    			return 1;
    		} else {
    			return 0;
    		}
    	}
    	
    	public String toString() {
    		return " " + this.name + " " + this.age;
    	}
    	
    	public static void main (String[] args) {
    		Student[] s = new Student[] {
    				new Student(18,"李")	,	
    				new Student(10,"王"),
    				new Student(6,"田"),
    				new Student(20,"张")
    		};
    		
    	
    		Set<Student> ts = new TreeSet<Student>();
    		for(int i = 0; i < s.length; i++)
    			ts.add(s[i]);
    		System.out.println(ts);
    		
    	}
    }
    
    输出:
    [ 田 6,  王 10,  李 18,  张 20]

    可以看到,这段代码实现了Comparable接口,也实现Comparable接口中的compareTo()方法,但是在这个程序中没有看对象调用compareTo()方法,那么compareTo方法是如何被调用的呢:

    TreeSet类的底层实现其实是TreeMap(虽然 TreeMap 和TreeSet 实现的接口规范不同,但 TreeSet 底层是通过 TreeMap 来实现的)在每次add的时候,也就是调用TreeMap的put方法这时,如果有外部比较器Comparator的实现就会调用外部的Comparator的比较方法,如果没有就会调用实现Comparable接口的类的compareTo方法

    我们来看一下Treeset的add()方法的源码:

    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
        }

    其中,m是TreeMap的一个实例,再看一下TreeMap中的put方法源码

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

    其中Comparable<? super K> k = (Comparable<? super K>) key;

    作用为:K类型的实例要实现Comparable接口

    在cmp = k.compareTo(t.key);

    作用为:调用自己实现的compareTo()方法,

    参考资料:

    inuyasha1的CSDN提问

  • 0
  • 0
  • 0
  • 3.8k
  • 请登录之后再进行评论

    登录
    单栏布局 侧栏位置: