馬會(huì)成
(1.寧夏職業(yè)技術(shù)學(xué)院,寧夏 銀川750002;2.寧夏廣播電視大學(xué),寧夏銀川750002)
在java.util數(shù)據(jù)包里有一個(gè) Properties類,它是JAVA集合類中的一個(gè)保存數(shù)據(jù)的類,通常用于處理軟件項(xiàng)目中的配置文件,Properties對(duì)象中的每一個(gè)數(shù)據(jù)保存的是一個(gè)鍵值對(duì),鍵和值是一一對(duì)應(yīng)關(guān)系,而且鍵必須是唯一的,否則就會(huì)發(fā)生數(shù)據(jù)覆蓋,也就是說(shuō),如果鍵出現(xiàn)了重復(fù),那么后保存的數(shù)據(jù)就會(huì)覆蓋以前保存的相同鍵對(duì)應(yīng)的數(shù)據(jù)。
Properties類能夠處理數(shù)據(jù)項(xiàng)對(duì)應(yīng)的屬性,而且它具有持久性,屬性的每個(gè)鍵和值可以是自定義對(duì)象,也可以是字符串,但更常見的是字符串,它既可以保存在流中也可以從流中加載,既可以在一個(gè)屬性列表中設(shè)定它的“默認(rèn)值”,也可以讓另一個(gè)屬性列表作為它的“默認(rèn)值”,Properties類的自動(dòng)同步功能和 它的setProperty方法提供的處理字符串的安全性,這些方便的功能使得在軟件項(xiàng)目中得到了越來(lái)越多的應(yīng)用。
需要注意的是,由于Properties類是從Hashtable繼承而來(lái),因而可以對(duì)Properties的對(duì)象應(yīng)用Hashtable中的put和putAll方法,但是不建議使用put和putAll方法,因?yàn)樗鼈冊(cè)试S調(diào)用者插入其鍵或值不是 String的項(xiàng),這將導(dǎo)致軟件和項(xiàng)目的安全性受到影響,建議使用setProperty方法。如果要使用Properties中的store、propertyNames、save、list方法,那么Properties對(duì)象中屬性必須是String類型的鍵和值。
Properties類雖然支持中文排序,但是它的局限性在于需要開發(fā)人員自行設(shè)計(jì)算法,并手工完成一些代碼,而且它沒有提供對(duì)自定義對(duì)象的排序算法及其實(shí)現(xiàn),將自定義對(duì)象作為Properties的鍵進(jìn)行中文排序的算法,將會(huì)使得Properties類的方便性和實(shí)用性得到進(jìn)一步的擴(kuò)展。
Properties類還有一種局限,那就是它既沒有提供按指定的屬性對(duì)自定義對(duì)象進(jìn)行排序的算法,也沒有提供可以直接對(duì)自定義對(duì)象進(jìn)行排序的具體實(shí)現(xiàn),因而,Properties類按指定的屬性對(duì)自定義對(duì)象進(jìn)行排序的相關(guān)算法及其實(shí)現(xiàn),將使Properties類的功能得到進(jìn)一步發(fā)展和完善。
自定義對(duì)象作為Properties的鍵按鍵進(jìn)行排序時(shí),可以使用自定義對(duì)象的某個(gè)屬性值作為Properties的鍵,也可以使用將整個(gè)自定義對(duì)象作為Properties的鍵,而且通常排序還有正向排序和反向排序之分,排序字符串也有中文和英文之分,現(xiàn)將自定義對(duì)象作為Properties的鍵進(jìn)行中文排序的算法概述如下:
如果你只關(guān)心一個(gè)自定義對(duì)象的一個(gè)屬性或者值并對(duì)其使用排序,且用于排序的屬性不會(huì)重復(fù),那么可以將該屬性用于Properties的鍵,如果屬性值重復(fù),那么后出現(xiàn)的屬性值將覆蓋前面的出現(xiàn)的屬性值,而不用將整個(gè)自定義對(duì)象保存到Properties中,比如,有一個(gè)學(xué)生類,其中的學(xué)號(hào)不可能重復(fù),所以學(xué)號(hào)可以做為Properties的鍵,并可以按學(xué)號(hào)進(jìn)行排序,基本實(shí)現(xiàn)算法如下:
①由于是自定義對(duì)象的排序,所以首先要有一個(gè)類,這樣才能生成自定義對(duì)象,比如學(xué)生類,在類中提供學(xué)號(hào)、姓名等屬性。
②由于是對(duì)自定義對(duì)象的屬性進(jìn)行排序,所以需要先寫一個(gè)類CollatorComparator,且該類要實(shí)現(xiàn)Comparator接口。在該類中要提供一個(gè)方法compare,用于處理自定義對(duì)象中按指定的屬性進(jìn)行排序。
③用自定義類生成自定義對(duì)象,并進(jìn)行初始化,然后用Properties類生成一個(gè)對(duì)象defList,并用生成的對(duì)象defList通過setProperty方法將自定義對(duì)象的屬性作為鍵和值對(duì)defList進(jìn)行初始化。注意,這里排序關(guān)鍵字不能重復(fù),如果重復(fù),將覆蓋前面的有相同屬性的對(duì)象,除非預(yù)知此結(jié)果,否則請(qǐng)不要使用此種覆蓋。
④用上面自己寫的類CollatorComparator生成一個(gè)對(duì)象的實(shí)例comparator。
⑤用new ArrayList(defList.entrySet())生成一個(gè)實(shí)例,并保存到List類的對(duì)象list1中。
⑥用 Collections.sort(list1,comparator);實(shí)現(xiàn)對(duì)對(duì)象 list1按comparator的規(guī)則進(jìn)行排序。
⑦用List類的對(duì)象list1調(diào)用iterator(),并保存到Iterator類的對(duì)象i中。
⑧然后用一個(gè)循環(huán)處理Properties的鍵和值,這里要注意鍵和值的對(duì)應(yīng)關(guān)系,可以使用i.next()得到下一個(gè)鍵,并轉(zhuǎn)換成Map.Entry的類的對(duì)象,同時(shí)保存到Map.Entry的對(duì)象me中,這樣me.getKey()保存的就是Properties的當(dāng)前正在處理的鍵,而me.getValue()就是對(duì)應(yīng)鍵的值。
上面在Properties中保存的都是對(duì)象的部分值,這樣是為了方便按鍵的排序,如果想在Properties中保存完整的對(duì)象,那么就可以按對(duì)象的任何一個(gè)屬性進(jìn)行排序。
將自定義對(duì)象中用于排序的屬性作為Properties的鍵,往往存在著屬性值的重復(fù)問題,為了解決這個(gè)問題,可以將整個(gè)自定義對(duì)象作為Properties的鍵,這樣只要自定義對(duì)象不同,不管他們用于排序的屬性值是否相同,都可以將自定義對(duì)象作為Properties的鍵,并可以按需要的屬性進(jìn)行排序,但是需要注意的是,如果自定義對(duì)象相同,那么后出現(xiàn)的對(duì)象將覆蓋前面出現(xiàn)過的對(duì)象。這種方案比較器兩個(gè)參數(shù)的類型常有兩種:Object和Map.Entry型,這里先看Object型。
●比較器兩個(gè)參數(shù)的類型使用Object型,基本實(shí)現(xiàn)算法如下:
①由于是自定義對(duì)象的排序,所以首先要有一個(gè)類,這樣才能生成自定義對(duì)象,比如Person類,在類中提供年齡、姓名等屬性。
②由于是將整個(gè)自定義對(duì)象作為Properties的鍵,而且只是對(duì)自定義對(duì)象的屬性進(jìn)行排序,所以需要先寫一個(gè)類CollatorComparator,且該類要實(shí)現(xiàn)Comparator接口。在該類中要提供一個(gè)方法compare,用于處理自定義對(duì)象中按指定的屬性進(jìn)行排序,該類的主要代碼如下:
Collator collator=(RuleBasedCollator)java.text.Collator.getInstance (java.util.Locale.CHINA);
注意,上面的代碼由于用了toString(),所以什么類型都可以比較如int型。使用此法時(shí),如果不區(qū)分大小寫,只需要在這兩個(gè)toString()后加上.toLowerCase(),或者用.toUpperCase()。如果要反向排序,只需要在key1前加負(fù)號(hào)。
③用自定義類生成自定義對(duì)象,并進(jìn)行初始化,然后用Properties類生成一個(gè)對(duì)象defList,并用生成的對(duì)象defList通過put方法將自定義對(duì)象的屬性作為鍵和值對(duì)defList進(jìn)行初始化。注意,這里排序關(guān)鍵字的值可以重復(fù),而且只要自定義對(duì)象不重復(fù),即使排序?qū)傩灾抵貜?fù)也不存在導(dǎo)致覆蓋的問題。
④用上面自己寫的類 CollatorComparator一個(gè)對(duì)象的實(shí)例comparator。
⑤用Properties類生成的對(duì)象defList調(diào)用keySet()中的toArray()方法,并保存到Object型的數(shù)組key中。
⑥用Arrays.sort(key,comparator)對(duì)數(shù)組key按comparator規(guī)則進(jìn)行排序。
⑦然后用一個(gè)循環(huán)處理Properties的鍵和值,這里要注意鍵和值的對(duì)應(yīng)關(guān)系,(Person)key[i]保存的就是Properties的當(dāng)前正在處理的鍵,而defList.get(key[i])就是對(duì)應(yīng)鍵的值。
上面的方法在比較器的參數(shù)是兩個(gè)Object直接轉(zhuǎn)換成Person對(duì)象,這就要求比較時(shí)將比較器用于裝有Person對(duì)象的容器,這只是方法中的一種.
當(dāng)然我們也可以將比較器的兩個(gè)參數(shù)的Object轉(zhuǎn)換成Properties操作需要的Map.Entry型,這就要求比較時(shí)將比較器用于裝有鍵值的Properties對(duì)象,然后對(duì)person類的屬性name進(jìn)行排序(包括中英文)。
●比較器兩個(gè)參數(shù)的類型使用Map.Entry型,基本實(shí)現(xiàn)算法如下:
①由于是自定義對(duì)象的排序,所以首先要有一個(gè)類,這樣才能生成自定義對(duì)象,比如Person類,在類中提供年齡、姓名等屬性。
②由于是將整個(gè)自定義對(duì)象作為Properties的鍵,而且只是對(duì)自定義對(duì)象的屬性進(jìn)行排序,所以需要先寫一個(gè)類CollatorComparator,且該類要實(shí)現(xiàn)Comparator接口。在該類中要提供一個(gè)方法compare,用于處理自定義對(duì)象中按指定的屬性進(jìn)行排序,該類的主要代碼如下:
Collator collator=(RuleBasedCollator)java.text.Collator.getInstance (java.util.Locale.CHINA);
注意,上面的代碼由于用了toString(),所以什么類型都可以比較如int型。使用此法時(shí),如果不區(qū)分大小寫,只需要在這兩個(gè)toString()后加上.toLowerCase(),或者用.toUpperCase()。如果要反向排序,只需要在key1前加負(fù)號(hào)。
③用自定義類生成自定義對(duì)象,并進(jìn)行初始化,然后用Properties類生成一個(gè)對(duì)象defList,并用生成的對(duì)象defList通過put方法將自定義對(duì)象的屬性作為鍵和值對(duì)defList進(jìn)行初始化。注意,這里排序關(guān)鍵字的值可以重復(fù),而且只要自定義對(duì)象不重復(fù),即使排序?qū)傩灾抵貜?fù)也不存在導(dǎo)致覆蓋的問題。
④用上面自己寫的類 CollatorComparator一個(gè)對(duì)象的實(shí)例comparator。
⑤用new ArrayList(defList.entrySet())生成一個(gè)實(shí)例,并保存到List類的對(duì)象list1中。
⑥用 Collections.sort(list1,comparator);;實(shí)現(xiàn)對(duì)對(duì)象 list1按comparator的規(guī)則進(jìn)行排序。
⑦用List類的對(duì)象list1調(diào)用iterator(),并保存到Iterator類的對(duì)象i中。
⑧然后用一個(gè)循環(huán)處理Properties的鍵和值,這里要注意鍵和值的對(duì)應(yīng)關(guān)系,可以使用i.next()得到下一個(gè)鍵,并轉(zhuǎn)換成Map.Entry的類的對(duì)象,同時(shí)保存到Map.Entry的對(duì)象me中,這樣(Person)me.getKey()保存的就是Properties的當(dāng)前正在處理的鍵即整個(gè)自定義對(duì)象,而me. getValue()就是對(duì)應(yīng)鍵的值。
在實(shí)際使用中,將自定義對(duì)象作為Properties的值的情況更為常見,因?yàn)樽远x對(duì)象作為Properties的鍵時(shí),如果自定義對(duì)象相同,會(huì)有覆蓋的情況,而做為值就不會(huì)出現(xiàn)覆蓋的情況,而且用值時(shí)對(duì)其中的相關(guān)屬性排序時(shí)控制更方便。
[1][美]Robert Lafore.Java數(shù)據(jù)結(jié)構(gòu)和算法[M].
[2]sun公司官方網(wǎng)站.JDK幫助文檔[OL].