徐秀勤
摘要:本文基于集合學(xué)習(xí),介紹如何設(shè)計一個比較完善的應(yīng)用類。通過HashSet介紹了在應(yīng)用類中添加equals0方法和hashCode()方法,通過TreeSa介紹了應(yīng)用類需要實現(xiàn)Comparable接口并實現(xiàn)繼承的compareTo()方法。
關(guān)鍵詞:集合;類;教學(xué)設(shè)計
中圖分類號:G642 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2019)27-0087-02
集合(Set)是Java中一個很重要的可以用來存儲和處理無重復(fù)元素的高效的數(shù)據(jù)結(jié)構(gòu)。比如說可以存儲和處理一個單位的部門名稱,存儲和處理一個國家的省城名稱,或者奧運會時參賽國家的名稱等,這幾個信息的處理都是要求不可重復(fù)的。那么在實際應(yīng)用中,使用集合存儲和處理相關(guān)問題時,應(yīng)該如何設(shè)計這個應(yīng)用類,確保其元素不可重復(fù)存儲呢?
1集合Set
集合Set是一個接口,它繼承了Collection接口中所有的方法。Set接口本身不能實例化,但是可以作為類型使用,只是規(guī)定其實例不能包含重復(fù)的元素。在一個集合中,當(dāng)要添加一個新元素時,要先判斷這個元素的散列碼(hashcode值)在原集合的哈希表中是否存在。如果不存在,則新元素可以立即加入;如果存在,則再檢查equals()方法,即新元素通過調(diào)用其自身的equals()方法,跟原集合中所有的元素都進行比較,如果存在結(jié)果為true的情況,則新元素不能加入,否則新元素可以加入。
Set有三個實現(xiàn)的具體的子類,分別是HashSet、Hnked-HashSet和TreeSet,這三個類也是必須確保不能向集合中添加重復(fù)的元素。關(guān)于集合的操作與訪問是集合教學(xué)的一個重要方面,但是本文限于篇幅不作特別介紹。
2散列集HashSet
HashSet是一個實現(xiàn)了Set接口的散列集,可以使用它的無參構(gòu)造方法來創(chuàng)建空的散列集,也可以由一個現(xiàn)有的集合來創(chuàng)建一個散列集。HashSet類的實例用來存儲互不相同的任何元素,但允許null元素。該集合的元素是無序的、高效率的。在教學(xué)過程中,為讓學(xué)生理解這個特點,會創(chuàng)建一個HashSet實例,存放一些字符串對象并輸出集合,具體見【示例1】。
【示例1】主要代碼如下:
Set set=Hew HashSet();//創(chuàng)建一個空集合,可以放任何對象
set.add(”南京“)//將字符串對象“南京”存人集合set中
set.add(”南京”);//這個“南京”不會重復(fù)存入集合中;
set.add(“Nanjing”);//將字符串對象“Nanjing”存人集合set中
set.add(“nanjing”);//將字符串對象“nanjing”存人集合set中,注意與“Nanjing”不同
setl.add(12);//12會被包裝成對象存入集合set中,
svstem.out.println(setl;//輸出集合set中所有元素
上述程序代碼最終運行結(jié)果顯示集合中只有“南京、Nan-jing、nanjing、12”這四個元素。多次運行,會發(fā)現(xiàn)次序有變化,但是元素不變。能達(dá)到這效果的原因是,String類已經(jīng)重寫了equal()方法與hashCode()方法,排除了重復(fù)的元素。
那么如果集合set中存儲圓類對象,能確保不重復(fù)嗎?首先設(shè)計【示例2】圓類如下:
class Circle{
private double r;
Circle(double r){this.r=r;}
//省略r的get、set方法與求面積與周長等其他方法;
pubhc String toString0{return”r=”+r;}//重寫這個方法,顯示圓對象信息
}
在【示例1】的最后輸出語句之前添加兩行相同的代碼"set.add(new Cirlce(5));”
重新運行【示例1】程序,會發(fā)現(xiàn)輸出的集合元素中會出現(xiàn)兩個“r=5.0”:
為避免上述問題,需要改寫【示例2】的Cidce類,重寫equals()方法與hashCode()方法。在講授這個集合內(nèi)容之前,學(xué)生已經(jīng)掌握了如何正確寫出Circle類的equals方法。由此可以先讓學(xué)生在Cirlce類中正確添加equals()方法后,再次運行【示例1】,發(fā)現(xiàn)兩個半徑為5的圓依然存在。說明一個類僅僅重寫equals()方法是不夠的,必須還要重寫hashCode()方法。該方法原型如下:
public int hashCode(){}
hashCode()方法其實就是要求返回一個整型的散列碼(hashCode值)。要求相同對象的散列碼一樣即可,意味著不相同的元素的散列碼可以一樣也可以不一樣。對于一個由半徑值來描述圓的對象,半徑相同其散列碼相同即可。那么直接將半徑取整返回即可,hashCode()方法代碼如下:
pubhc im hashCode(){return(inI)r;}
上述代碼表示,假如圓半徑的整數(shù)部分相同,則它們的散列碼相同,在集合中會再去處理equals方法,才能判斷它們究竟算不算相同的對象。例如半徑為5.00000-5.99999,它們的散列碼都是5。如果圓半徑精度要求達(dá)到4位小數(shù),那么為了提高效率,可以考慮把半徑值擴大后再取整返回即可,修改代碼如下:
public im hashCode(){return(inI)(r*10000);}
當(dāng)然還有其他方法,可以利用String類中已經(jīng)實現(xiàn)的hash-Code()方法,把double類型的r轉(zhuǎn)換成String類型,則可以直接調(diào)用其本身的hashCodeO方法即可。因此Circle類中的hashCode()方法還可以修改如下:
public int hashCode0{return(r+””).hashCode();J
在教學(xué)過程中發(fā)現(xiàn),學(xué)生重寫某個類的hashCode方法總是不知如何下手,其實只要確保某元素重要屬性值相同,其散列碼相同即可。想辦法把類中描述元素的重要屬性值轉(zhuǎn)換成整型數(shù)據(jù)返回或轉(zhuǎn)換成字符串調(diào)用其hashCode()方法返回即可,非常簡單。
3鏈?zhǔn)郊螸inkedHashSet
LinkedHashSet是HashSet的子類,它支持集合內(nèi)的元素是有序的,不過這個次序是按照集合添加元素的次序的方式排序的。復(fù)制【示例1】得到【示例3】,并修改第一行代碼:
Set set=new LinkedHashSet();
其余代碼不變,運行【示例3】,多次運行,發(fā)現(xiàn)輸出的集合中的元素沒有重復(fù),且與添加的順序一致,這個特點學(xué)生還是比較容易理解并接受的。
4樹形集合TreeSet
Set接口的一個子接口SortedSet可以確保集合中的元素是有序的。TreeSet實現(xiàn)了SortedSet接口,通過無參構(gòu)造方法可以創(chuàng)建一個空的TreeSet對象。只要對象是可以比較的,就可以將它們添加到一個TreeSet對象中。先設(shè)計一個只能添加字符串對象的TreeSet對象,讓學(xué)生理解TreeSet與HashSet的不同特點。
【示例4】主要代碼如下:
Setset=new TreeSet();//考慮集合只能存人String對象
set.add("naniing");
在實際應(yīng)用中,如果需要用集合來存儲和處理對象,則該對象的原類除了包含正常封裝的數(shù)據(jù)成員,一些必要的業(yè)務(wù)處理的方法外,還需要重寫hashCode()和equals()方法;如果業(yè)務(wù)上還要求需要有序存儲,那么對象的原類還必須實現(xiàn)compara-ble接口,實現(xiàn)從接口繼承的compareTo()方法。通過集合基本特點的介紹,希望大家對如何設(shè)計一個相對比較完善的應(yīng)用類能有所幫助。
【通聯(lián)編輯:光文玲】