Set接口與上文所講的List接口的區別是:
不能加入重複的元素;
接口的實例無法像List接口那樣可以進行雙向輸出;
List接口對Collection接口進行了擴充,Set沒有對Collection進行擴充,只是比Collection要求更嚴格了(不能加重複元素)。
set接口下面有兩個常用的子類:HashSet、TreeSet和一個子接口SortedSet,下面對這幾個一一介紹。
HashSet、TreeSet:Set--->無重複,Hash---->無序,Tree---->有序
本節主要介紹TreeSet的排序,去重;HashSet的去重。
1、散列存放:HashSet
hashset的實現依賴hash函數,哈希值。主要特點,裏面不能存放重複的元素,採取散列的存儲方式,所以沒有順序。
2、有序的存放:TreeSet
程序在向集合插入數據的時候是無序的,輸出是有序的。
需要說明以下的例子並沒有證明HashSet的無序性,以後在深入研究一下。現在先看一下他們的使用
public class HashSetDemo01 {
public static void main(String[] args) {
Set<String> allSet = new HashSet<String>();
allSet.add("A");
allSet.add("B");
allSet.add("D");
allSet.add("D");//重複元素不能加入
allSet.add("C");
allSet.add("E");
System.out.println(allSet);
Set<String> allSet1 = new TreeSet<String>();
allSet1.add("E");
allSet1.add("C");
allSet1.add("B");
allSet1.add("C");//重複元素不能加入
allSet1.add("A");
allSet1.add("D");
System.out.println(allSet1);
}
}
輸出結果:
[A, B, C, D, E]
[A, B, C, D, E]
怎樣實現TreeSet的排序呢?TreeSet中元素是有序存放的,所以對於每一個對象必須指定好排序規則,而且TreeSet中的每個對象所在的類必須實現Comparable接口纔可以正常使用。
如果你想對自己寫的類排序,你就把自己寫的這個類實現Comparable接口,然後重寫comparaTo方法來規定這個類的對象排序的順序。
在這個方法中,如果返回-1,則當前對象排前面;返回1,就排後面 ;0,就相等。
public class TreeSetDemo01 {
/**
* TreeSet排序
* @param args
*/
public static void main(String[] args) {
Set<Person> allSet = new TreeSet<Person>();
allSet.add(new Person("張三", 20));
allSet.add(new Person("李四", 22));
allSet.add(new Person("王五", 24));
allSet.add(new Person("王五", 24));
allSet.add(new Person("趙六", 28));
allSet.add(new Person("趙七", 28));
System.out.println(allSet);//如果不重寫toString的話則輸出的是地址
}
}
class Person implements Comparable<Person>{//定義一個Person類,實現比較器
private String name;
private int age;
// 通過構造方法爲屬性賦值
public Person(String name, int age){
this.name = name;
this.age = age;
}
// 爲了輸入方便,重寫toString方法,如果重寫toString的話則輸出的是地址
public String toString(){
return "姓名:"+this.name+";年齡:"+this.age;
}
// 排序規則
@Override
public int compareTo(Person person) {
if(this.age > person.age){
return 1;//this.age排後面
}else if(this.age < person.age){
return -1;//this.age排前面
}else{
return this.name.compareTo(person.name);//增加字符串比較,年齡相等的話區分姓名
} //如果姓名年齡都相等的話,爲重複元素,不再排出來
}
}
輸出結果:
[姓名:張三;年齡:20, 姓名:李四;年齡:22, 姓名:王五;年齡:24, 姓名:趙七;年齡:28, 姓名:趙六;年齡:28]
以上例子實現了TreeSet“去重複”、“排序”的功能,都是通過Comparable接口完成的。
然而對於HashSet此方法不能“去重”、”排序“,HashSet是無法排序的,他本身存儲是無序的,排序無用,同時Comparable接口中實現的”去重“方法也不能實現了。
那麼,如何針對HashSet進行去重複元素呢?
4、HashSet(後面會講到HashMap)利用equals、HashCode去重複元素
equals--->判斷對象是否相等;
HashCode--->判斷對象的編碼是否相等
class Person2 {
private String name;
private int age;
public Person2(String name, int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
if(this == obj){
return true;//地址相同是同一個對象
}
if(!(obj instanceof Person2)){
return false;//傳遞過來的不是本類對象,不是同一個對象
}
Person2 p = (Person2) obj;//向下轉型
if(this.name.equals(p.name)&&this.age == p.age){//全部屬性相等,是同一個對象
return true;
}else{
return false;
}
}
public int hashCode(){//重寫HashCode
return this.name.hashCode()*this.age;
}
public String toString(){
return "姓名:"+this.name+";年齡:"+this.age;
}
}
public class TreeSetDemo01 {
/**
* HashSet去重
* @param args
*/
public static void main(String[] args) {
Set<Person2> allSet1 = new HashSet<Person2>();
allSet1.add(new Person2("張三", 20));
allSet1.add(new Person2("李四", 22));
allSet1.add(new Person2("王五", 24));
allSet1.add(new Person2("王五", 24));
allSet1.add(new Person2("趙六", 28));
allSet1.add(new Person2("趙七", 28));
System.out.println(allSet1);
}
}
輸出結果:
[姓名:趙七;年齡:28, 姓名:李四;年齡:22, 姓名:張三;年齡:20, 姓名:趙六;年齡:28, 姓名:王五;年齡:24]
以上就是HashSet去重複元素的實現。
下文介紹Map接口。