TreeSet和TreeMap的輸出


如果加入TreeSet和TreeMap的元素沒有實現comprable中的compareTo()方法,那么會報錯“treeset cannot be cast to java.lang.Comparable”.

要解決這個問題有兩種方法:

(1)讓元素自身具有比較性;可以實現Comparable接口,實現compareTo()方法;

(2)讓集合自身具有比較性;可以定義比較器,即讓集合實現Comparator接口,然后實現compare()方法;

 

方法一:

因此需要對元素類型實現Comparable借口,並實現compareTo()方法,即告訴TreeSet和TreeMap你要怎么排列,它才能進行排序。

基礎類:

package niukewang;

import java.util.Objects;

public class setClass implements Comparable<setClass>{

    String a;
    String b;
    public setClass(String a, String b)
    {
        this.a=a;
        this.b=b;    
    }
    
    public int hashCode() {
        return a.hashCode();
    }
    
    public boolean equals(Object obj)
    {
        if(obj==null) return false;
        
        if(getClass() != obj.getClass()) return false;
        
        final setClass s=(setClass)obj;
        
        return Objects.equals(this.a, s.a);
    }

    @Override
    public int compareTo(setClass o) { int num=this.b.compareTo(o.b); return num; } }

測試類:

package niukewang;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Vector;


public class test1 {

    public static void main(String args[]) 
    { 
        setClass s1=new setClass("http://www.yjbys.com/", "same0");
        setClass s2=new setClass("http://www.yjbys.com1/", "same0");
        setClass s3=new setClass("http://www.yjbys.com2/", "same2");
        setClass s4=new setClass("http://www.yjbys.com2/", "same3");
        
        //hasSet
        System.out.println("hasSet......");
        Set<setClass> set=new HashSet<setClass>();
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        Iterator it= set.iterator();
        while(it.hasNext())
        {
            setClass ob=(setClass)it.next();
            System.out.println(ob.a);
        }
        
        //TreeSet
        System.out.println("\nTreeSet........"); Set<setClass> tree=new TreeSet<setClass>(); tree.add(s1); tree.add(s2); tree.add(s3); tree.add(s4); Iterator treeit=tree.iterator(); while(treeit.hasNext()) { setClass ob=(setClass) treeit.next(); System.out.println(ob.a); } //TreeMap
        System.out.println("\nTreeMap.........");
        Map<setClass,String> treemap=new TreeMap<setClass,String>();
        treemap.put(s1, "TreeMap one");
        treemap.put(s2, "TreeMap two");
        treemap.put(s3, "TreeMap three");
        treemap.put(s4, "TreeMap four");
        for(Map.Entry<setClass, String> entry: treemap.entrySet())
        {
            System.out.println("The treemap key is "+entry.getKey().a+" The value is "+ entry.getValue());
        }
        
        //HasMap
        System.out.println("\nHashMap......");
        Map<setClass,String> hashmap=new HashMap<setClass, String>();
        hashmap.put(s1, "HashMap one");
        hashmap.put(s2, "HashMap two");
        hashmap.put(s3, "HashMap three");
        hashmap.put(s4, "HashMap four");
        for(Map.Entry<setClass, String> entry : hashmap.entrySet())
        {
            System.out.println("The key is "+entry.getKey().a+" The value is "+entry.getValue());
        }
        
        //HasTable
        System.out.println("\nHashTable......");
        Map<setClass,String> hashtable=new Hashtable<setClass, String>();
        hashtable.put(s1, "HashTable one");
        hashtable.put(s2, "HashTable two");
        hashtable.put(s3, "HashTable three");
        hashtable.put(s4, "HashTable four");
        for(Map.Entry<setClass, String> entry: hashtable.entrySet())
        {
            System.out.println("The HashTable key is "+entry.getKey().a+" The HashTable value is "+entry.getValue());
        }
        
        //LinkedList
        System.out.println("\nLinkedList.....");
        List list=new LinkedList();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        Iterator listit=list.iterator();
        while(listit.hasNext())
        {
            setClass ob=(setClass)listit.next();
            System.out.println(ob.a);
        }

        //ArrayList
        System.out.println("\nArrayList.....");
        List array=new ArrayList();
        array.add(s1);
        array.add(s2);
        array.add(s3);
        array.add(s4);
        Iterator arrayit=array.iterator();
        while(arrayit.hasNext())
        {
            setClass ob=(setClass)arrayit.next();
            System.out.println(ob.a);
        }
        
        //vector
        System.out.println("\nvector.....");
        Vector v=new Vector();
        v.add(s1);
        v.add(s2);
        v.add(s3);
        v.add(s4);
        Iterator vit=v.iterator();
        while(vit.hasNext())
        {
            setClass  ob=(setClass)vit.next();
            System.out.println(ob.a);
        }
            
    }
}

 

輸出結果:

hasSet......
http://www.yjbys.com1/
http://www.yjbys.com/
http://www.yjbys.com2/
 TreeSet........ http://www.yjbys.com/
http://www.yjbys.com2/
http://www.yjbys.com2/

TreeMap.........
The treemap key is http://www.yjbys.com/ The value is TreeMap two
The treemap key is http://www.yjbys.com2/ The value is TreeMap three
The treemap key is http://www.yjbys.com2/ The value is TreeMap four

HashMap......
The key is http://www.yjbys.com1/ The value is HashMap two
The key is http://www.yjbys.com/ The value is HashMap one
The key is http://www.yjbys.com2/ The value is HashMap four

HashTable......
The HashTable key is http://www.yjbys.com1/ The HashTable value is HashTable two
The HashTable key is http://www.yjbys.com/ The HashTable value is HashTable one
The HashTable key is http://www.yjbys.com2/ The HashTable value is HashTable four

LinkedList.....
http://www.yjbys.com/
http://www.yjbys.com1/
http://www.yjbys.com2/
http://www.yjbys.com2/

ArrayList.....
http://www.yjbys.com/
http://www.yjbys.com1/
http://www.yjbys.com2/
http://www.yjbys.com2/

vector.....
http://www.yjbys.com/
http://www.yjbys.com1/
http://www.yjbys.com2/
http://www.yjbys.com2/

TreeSet並不像hashSet那樣,用hashCode和equals取決於元素是否相等。
而是取決於compareTo()方法中指定的排序的方式;

  setClass s1=new setClass("http://www.yjbys.com/", "same0");
  setClass s2=new setClass("http://www.yjbys.com1/", "same0");
  setClass s3=new setClass("http://www.yjbys.com2/", "same2");
  setClass s4=new setClass("http://www.yjbys.com2/", "same3");

如果用hashCode和equals取決於元素是否相等,那么s3和s4是相等的;

而此時候,是根據compareTo()方法中的第二個字符串b來判斷是否相等,則s1與s2相等,s3和s4不相等,所以才有這樣的輸出:

TreeSet........
http://www.yjbys.com/
http://www.yjbys.com2/
http://www.yjbys.com2/

 

方法二:

定義比較器,讓集合實現Comparator接口,然后實現compare方法,則集合自身具有比較性。

其中Class Student 是實現了Comparable接口的,是元素本身具有比較性,在main方法中添加到TreeSet中的時候,能體現出來,通過年齡來比較大小;如果年齡和姓名相同,則是完全相等;

其中成員方法testComparator()中,定義了一個TreeSet,使其實現Comparator接口,並實現了方法compare(),通過setClass類中的a的屬性的大小;因此此方法中的TreeSet具有比較性;

 

package niukewang;

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

import org.junit.Test;

//非線程安全
public class TreeSetTest {
    /**
     * TreeSet:它可以給Set集合中的元素進行指定方式的排序。 保證元素唯一性的方式:通過比較的結果是否為0. 底層數據結構是:二叉樹。
     * 
     * 排序的第一種方式: 讓元素自身具備比較性。只要讓元素實現Comparable接口,覆蓋compareTo方法即可。
     * 
     * 但是,如果元素自身不具備比較性,或者元素自身具備的比較性,不是所需要的。
     * 比如,學生的自然排序是按年齡排序,現在想要按照學生姓名排序。還可以不改動原有代碼。 這時怎么辦呢?
     * 
     * 排序的第二種方式:自定比較器的方式。這時可以讓集合自身具備比較性。
     * 
     * 可以定義一個類實現Comparator接口,覆蓋compare方法。
     * 將該Comparator接口子類對象作為實際參數傳遞給TreeSet集合構造函數。
     */
    public static void main(String[] args) {
        TreeSet<Student> ts = new TreeSet<Student>();
        // Student如果不實現Comparable,add時會出錯,Student cannot be cast to java.lang.Comparable
        //添加第一個對象時,TreeSet里沒有任何元素,所以沒有問題;
        //當添加第二個Err對象時,TreeSet就會調用該對象的compareTo(Object obj)方法與集合中其他元素進行比較——
        //如果對應的類沒有實現Comparable接口,則會引發ClassCastException異常
        // add方法內部會對插入的數據進行排序,此時元素自身具備比較性,因為其實現了Comparable接口
        ts.add(new Student("lisi0", 30));
        ts.add(new Student("lisixx", 29));
        ts.add(new Student("lisi9", 29));
        ts.add(new Student("lisi8", 38));
        // 重復插入無效,但是不報錯(根據年齡和名字進行比較,都相同,視為同一個學生)
        ts.add(new Student("lisixx", 29));
        ts.add(new Student("lisixx", 28));
        ts.add(new Student("lisi4", 14));
        ts.add(new Student("lisi7", 27));
        System.out.println(ts);
        
        System.out.println("testComparator........\n");
        TreeSetTest ob=new TreeSetTest();
        ob.testComprator();
    }
    
    //自定義比較器,讓集合自身具備比較性
    @Test
    public void testComprator()
    {
        setClass s1=new setClass("http://www.yjbys.com/", "same0");
        setClass s2=new setClass("http://www.yjbys.com1/", "same0");
        setClass s3=new setClass("http://www.yjbys.com2/", "same2");
        setClass s4=new setClass("http://www.yjbys.com2/", "same3");
        
        Set<setClass> treeset=new TreeSet<setClass>(new Comparator<setClass>(){

            @Override
            public int compare(setClass arg0, setClass arg1) {
                // TODO Auto-generated method stub
                int num=arg0.a.compareTo(arg1.a); //只比較屬性a的大小
                return num;
            }
        });
        
        treeset.add(s1);
        treeset.add(s2);
        treeset.add(s3);
        treeset.add(s4);

        System.out.println(treeset);
    }

    //同姓名同年齡的學生視為同一個學生
    public static class Student implements Comparable<Student> {

        private int age;
        private String name;

        public Student(String name, int age) {
            this.age = age;
            this.name = name;
        }

        @Override
        public int compareTo(Student stu) {
            int num = new Integer(this.age).compareTo(new Integer(stu.age));
            return num == 0 ? this.name.compareTo(stu.name) : num;
        }

        public String toString() {
            return name + "::" + age;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

運行結果:

[lisi4::14, lisi7::27, lisixx::28, lisi9::29, lisixx::29, lisi0::30, lisi8::38]
testComparator........

[http://www.yjbys.com/ :: same0, http://www.yjbys.com1/ :: same0, http://www.yjbys.com2/ :: same2]

由上圖可知:
Stuent類是通過年齡判斷的,所以按年齡排序;只有姓名和年齡都相同時,則認為是相同的,所以ts.add(new Student("lisixx", 29))不會重復添加;其他因為姓名不同,就算年齡相同,也認為是不相同的;

setClass類,是根據setClass中的屬性a的值是否相等,就算hashCode和equals方法被重寫了,它只看比較性。

 

注意:

如果在setClass類中,如果沒有重寫public String toString()方法,則會輸出類似下面的輸出:

[niukewang.setClass@cbf33da, niukewang.setClass@8b2747d3, niukewang.setClass@8b2747f2]

但是如果重寫了public String toString()方法:

 public String toString()
 {
  return this.a+" :: "+this.b;
 }

則會輸出:[http://www.yjbys.com/ :: same0, http://www.yjbys.com1/ :: same0, http://www.yjbys.com2/ :: same2]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM