排序及重復元素去重的說明,TreeSet,HashSet


先看下面一段代碼:

package 類集;
import java.util.Set;
import java.util.TreeSet;
class Person{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String gtoString(){
        return "姓名:" + this.name + ";年齡:" + this.age ;
    }
};

public class test1{
    public static void main(String args[]){
        Set<Person> allSet = new TreeSet<Person>() ;
        allSet.add(new Person("張三",30)) ;
        allSet.add(new Person("李四",31)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("趙六",33)) ;
        allSet.add(new Person("孫七",33)) ;
        System.out.println(allSet) ;
    }
};

運行結果:

Exception in thread "main" java.lang.ClassCastException: 類集.Person cannot be cast to java.lang.Comparable
    at java.util.TreeMap.compare(TreeMap.java:1294)
    at java.util.TreeMap.put(TreeMap.java:538)
    at java.util.TreeSet.add(TreeSet.java:255)
    at 類集.test1.main(test1.java:19)

報錯。此時沒有排序,因為java.lang.comparable類導致。

comparable是進行排序的接口。一個對象數組要想排序需要依靠comparable接口完成。對於treeset一樣,要想進行排序,則對象所在的類也要依靠comparable接口

修改如下,要想排序,對象所在的類也要依靠comparable接口(繼承之)

package 類集;
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person>{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String toString(){
        return "姓名:" + this.name + ";年齡:" + this.age ;
    }
    public int compareTo(Person per){  //這里需要復習comparable接口的知識 if(this.age>per.age){
            return 1 ;
        }else if(this.age<per.age){
            return -1 ;
        }else{
            return 0 ;
        }
    }
};
public class test1{
    public static void main(String args[]){
        Set<Person> allSet = new TreeSet<Person>() ;
        allSet.add(new Person("張三",30)) ;
        allSet.add(new Person("李四",31)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("趙六",33)) ;
        allSet.add(new Person("孫七",33)) ;
        System.out.println(allSet) ;
    }
};

輸出結果:

[姓名:張三;年齡:30, 姓名:李四;年齡:31, 姓名:王五;年齡:32, 姓名:趙六;年齡:33]

string類既然可以使用TreeSet排序,則String中肯定已經實現了Comparable接口。

string類定義如下:

public final class Stringextends Objectimplements Serializable, Comparable<String>, CharSequence

此時是可以排序了,但是結果有問題,

[姓名:張三;年齡:30, 姓名:李四;年齡:31, 姓名:王五;年齡:32, 姓名:趙六;年齡:33]

發現去掉了重復的元素(王五),依靠的是comparable接口完成的。孫七沒有加入進來,因為孫七和趙6年齡是完全一樣的,而此時的comparable接口比較的只是年齡。

為了保證正確,所有的屬性都應該進行比較:改成如下:

package 類集;
import java.util.Set;
import java.util.TreeSet;
class Person implements Comparable<Person>{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String toString(){
        return "姓名:" + this.name + ";年齡:" + this.age ;
    }
    public int compareTo(Person per){
        if(this.age>per.age){
            return 1 ;
        }else if(this.age<per.age){
            return -1 ;
        }else{ return this.name.compareTo(per.name) ; // 調用String中的compareTo()方法  }
    }
};
public class test1{
    public static void main(String args[]){
        Set<Person> allSet = new TreeSet<Person>() ;
        allSet.add(new Person("張三",30)) ;
        allSet.add(new Person("李四",31)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("趙六",33)) ;
        allSet.add(new Person("孫七",33)) ;
        System.out.println(allSet) ;
    }
};

輸出結果:

[姓名:張三;年齡:30, 姓名:李四;年齡:31, 姓名:王五;年齡:32, 姓名:孫七;年齡:33, 姓名:趙六;年齡:33]

此時的去重元素並不是真正意義上的重復元素取消

用hashSet試試,hashset不排序。

package 類集;
import java.util.HashSet;
import java.util.Set;
class Person{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public String toString(){
        return "姓名:" + this.name + ";年齡:" + this.age ;
    }
};
public class test1{
    public static void main(String args[]){
        Set<Person> allSet = new HashSet<Person>() ;
        allSet.add(new Person("張三",30)) ;
        allSet.add(new Person("李四",31)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("趙六",33)) ;
        allSet.add(new Person("孫七",33)) ;    
        System.out.println(allSet) ;
    }
};

輸出結果:

[姓名:王五;年齡:32, 姓名:趙六;年齡:33, 姓名:孫七;年齡:33, 姓名:王五;年齡:32, 姓名:張三;年齡:30, 姓名:李四;年齡:31, 姓名:王五;年齡:32]

此時並沒有去掉重復的元素,該如何取消呢,  

如果要想去掉重復,則需要object類中兩個方法幫助。

1,hashcode():表示一個唯一編碼,一般通過計算表示。   

2)equals():進行對象的比較操作。

我們需要覆寫這兩個方法

package 類集;
import java.util.HashSet;
import java.util.Set;
class Person{
    private String name ;
    private int age ;
    public Person(String name,int age){
        this.name = name ;
        this.age = age ;
    }
    public boolean equals(Object obj){    // 覆寫equals,完成對象比較
        if(this==obj){
            return true ;
        }
        if(!(obj instanceof Person)){
            return false ;
        }
        Person p = (Person)obj ;    // 向下轉型
        if(this.name.equals(p.name)&&this.age==p.age){
            return true ;
        }else{
            return false ;
        }
    }
    public int hashCode(){
        return this.name.hashCode() * this.age    ; // 自己定義一個公式,如上所寫。
    }
    public String toString(){
        return "姓名:" + this.name + ";年齡:" + this.age ;
    }
};
public class test1{
    public static void main(String args[]){
        Set<Person> allSet = new HashSet<Person>() ;
        allSet.add(new Person("張三",30)) ;
        allSet.add(new Person("李四",31)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("王五",32)) ;
        allSet.add(new Person("趙六",33)) ;
        allSet.add(new Person("孫七",33)) ;    
        System.out.println(allSet) ;
    }
};

輸出結果:

[姓名:趙六;年齡:33, 姓名:王五;年齡:32, 姓名:張三;年齡:30, 姓名:李四;年齡:31, 姓名:孫七;年齡:33]

此時沒有了重復元素

 

如果要想使用Set,必須注意以上兩個問題,

1,一個好的類應該覆寫object類中的equals(),hashCode(),toString()三個方法,實際上在String()中已經覆寫完成了。

2,Set接口依靠hashCode()和equals()完成重復元素的判斷,關於這一點,在以后的Map接口中也有體現。

3,TreeSet依靠Comparable完成排序的操作


免責聲明!

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



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