java中的几种泛型类——HashSet、HashMap、TreeSet、TreeMap,遍历map,排序,HashTable比较
HashSet
HashSet<E>泛型類在數(shù)據(jù)組織上類似于數(shù)學(xué)上的集合,可以進(jìn)行“交”、“并”、“差”等運(yùn)算。 HashSet<E>泛型類創(chuàng)建的對(duì)象稱為集合,如: ? ? HashSet<E> set = ?HashSet<String>(); ? ? 那么set就是一個(gè)可以存儲(chǔ)string類型數(shù)據(jù)的集合,set可以調(diào)用add(String s)方法將string類型的數(shù)據(jù)添加到集合中。添加到集合中的數(shù)據(jù)稱為集合的元素。集合不允許有相同的元素。也就是說(shuō),如果b已經(jīng)是集合中的元素,那么執(zhí)行add(b)的操作是無(wú)效的。集合對(duì)象的初始容量是16字節(jié),裝載因子是0.75。也就是說(shuō),如果集合添加的元素超過(guò)總?cè)萘康?5%是,集合的容量將增加1倍。 相關(guān)運(yùn)算: 并運(yùn)算:boolean addAll(HashSet); 交運(yùn)算:boolean retainAll(HashSet); 差運(yùn)算:boolean remainAll(HashSet); 參數(shù)指定的集合必須與當(dāng)前集合是同種類型的集合,否則上述方法返回的類型是false。 HashSet<E>泛型類實(shí)現(xiàn)了泛型接口Set<E>,而Set<E>接口是Collection<E>接口的子接口。HashSet<E>類中的絕大部分方法都是接口方法的實(shí)現(xiàn)。編程時(shí),可以使用接口回調(diào)技術(shù),即把HashSet<E>對(duì)象的引用賦值給Collection<E>接口變量或Set<E>接口變量,那么接口就可以調(diào)用類實(shí)現(xiàn)的接口方法。HashMap
HashMap<K,V>對(duì)象成為散列映射對(duì)象。散列映射用于存儲(chǔ)鍵-值數(shù)據(jù)對(duì),允許把任何數(shù)量的鍵-值數(shù)據(jù)存儲(chǔ)在一起。鍵不可以可重復(fù)。如果出現(xiàn)兩個(gè)數(shù)據(jù)項(xiàng)的鍵相同,那么先前散列映射中的鍵-值對(duì)將被替換。散列映射在它需要更多存儲(chǔ)容量是會(huì)自動(dòng)增大容量。例如,如果散列映射的裝載因子是75%時(shí),它就自動(dòng)把容量增加到原始容量的2倍。對(duì)于數(shù)組和鏈表這兩種數(shù)據(jù)結(jié)構(gòu),如果要查找它們存儲(chǔ)的某個(gè)特定的元素卻不知道它們的位置,就需要從頭開始訪問(wèn)元素知道找到匹配的為止;如果數(shù)據(jù)結(jié)構(gòu)中包含很多元素,就會(huì)浪費(fèi)時(shí)間。這時(shí)最好使用散列映射來(lái)存儲(chǔ)要找的數(shù)據(jù),以便檢索時(shí)可以減少檢索的開銷。 HashMap<K,V>泛型類創(chuàng)建的對(duì)象稱為散列映射,如:? ? ?HashMap<K,V> hash = HashMap<String,Student>(); ? ? ?那么,hash就可以存儲(chǔ)鍵-值對(duì)數(shù)據(jù),其中的鍵必須是一個(gè)String對(duì)象,鍵對(duì)應(yīng)的值必須是Student對(duì)象。hash可以調(diào)用 public V put(K key, V value)方法將鍵-值對(duì)存儲(chǔ)在散列映射中,同時(shí)返回鍵所對(duì)應(yīng)的值。 ? ?遍歷散列映射的方法有如下四種:public static void main(String[] args) {Map<String, String> map = new HashMap<String, String>();map.put("1", "value1");map.put("2", "value2");map.put("3", "value3");// 第一種:普遍使用,二次取值System.out.println("通過(guò)Map.keySet遍歷key和value:");for (String key : map.keySet()) {System.out.println("key= " + key + " and value= " + map.get(key));}// 第二種System.out.println("通過(guò)Map.entrySet使用iterator遍歷key和value:");Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();while (it.hasNext()) {Map.Entry<String, String> entry = it.next();System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}// 第三種:推薦,尤其是容量大時(shí)System.out.println("通過(guò)Map.entrySet遍歷key和value");for (Map.Entry<String, String> entry : map.entrySet()) {System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());}// 第四種System.out.println("通過(guò)Map.values()遍歷所有的value,但不能遍歷key");for (String v : map.values()) {System.out.println("value= " + v);} }HashMap<E>泛型類是實(shí)現(xiàn)泛型接口Map<E>。
TreeSet
TreeSet<E>類是實(shí)現(xiàn)Set接口的類。TreeSet<E>泛型類創(chuàng)建的對(duì)象稱為樹集,如:
? ? ?TreeSet<Student> tree = TreeSet<Student>(); ? ? ?那么tree就是一個(gè)可以存儲(chǔ)Student對(duì)象的集合,tree可以調(diào)用add(Student s)方法將Student對(duì)象添加到樹集中。樹集采用樹結(jié)構(gòu)存儲(chǔ)數(shù)據(jù),樹集節(jié)點(diǎn)的排列和鏈表不同,不按添加的先后順序順序排列。樹集采用add()方法增加節(jié)點(diǎn),節(jié)點(diǎn)會(huì)按其存放的數(shù)據(jù)的“大小”順序一層一層地依次排序,同一層的節(jié)點(diǎn)按“大小”順序遞增排列,下一層的比上一層的小。樹集是一個(gè)有序集合。
TreeMap
TreeMap類實(shí)現(xiàn)了Map接口,TreeSet類提供了按排序順序存儲(chǔ)鍵-值對(duì)的有效手段。TreeMap保證它的元素按key升序排列。 構(gòu)造函數(shù)有2種: ? ?TreeMap<K,V>()按照關(guān)鍵字key的大小順序來(lái)對(duì)鍵-值對(duì)進(jìn)行升序排序,key的順序是按其字符串表示的字典順序。 ? ?TreeMap<K,V>(Comparator<K> comp)關(guān)鍵字key的大小順序按照Comparator接口規(guī)定的大小順序?qū)溆成渲械逆I-值對(duì)進(jìn)行排序,即可以升序,也可以降序,取決于里面重寫的方法。 ? ?下面是一個(gè)排序的例子: package test;import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.TreeMap;public class Sort {public static void main(String[] args) {System.out.println("開始:");Person person1 = new Person("馬先生", 220181);Person person2 = new Person("李先生", 220193);Person person3 = new Person("王小姐", 220186);Map<Number, Person> map = new HashMap<Number, Person>();map.put(person1.getIdCard(), person1);map.put(person2.getIdCard(), person2);map.put(person3.getIdCard(), person3);System.out.println("由HashMap類實(shí)現(xiàn)的Map集合,無(wú)序:");for (Iterator<Number> it = map.keySet().iterator(); it.hasNext();) {// 遍例集合Person person = map.get(it.next());System.out.println(person.getIdCard() + " " + person.getName());}System.out.println("由TreeMap類實(shí)現(xiàn)的Map集合,鍵對(duì)象升序:");TreeMap<Number, Person> treeMap = new TreeMap<Number, Person>();treeMap.putAll(map);for (Iterator<Number> it = treeMap.keySet().iterator(); it.hasNext();) {// 遍例集合Person person = treeMap.get(it.next());System.out.println(person.getIdCard() + " " + person.getName());}System.out.println("由TreeMap類實(shí)現(xiàn)的Map集合,鍵對(duì)象降序:");TreeMap<Number, Person> treeMap2 = new TreeMap<Number, Person>(Collections.reverseOrder());// 初始化為反轉(zhuǎn)排序treeMap2.putAll(map);for (Iterator it = treeMap2.keySet().iterator(); it.hasNext();) {// 遍例集合Person person = (Person) treeMap2.get(it.next());System.out.println(person.getIdCard() + " " + person.getName());}System.out.println("結(jié)束!");} }class Person {private String name;private long idCard;public Person(String name, long idCard) {this.name = name;this.idCard = idCard;}public long getIdCard() {return idCard;}public void setIdCard(long idCard) {this.idCard = idCard;}public String getName() {return name;}public void setName(String name) {this.name = name;} }? ? ?輸出結(jié)果為:開始: 由HashMap類實(shí)現(xiàn)的Map集合,無(wú)序: 220186 王小姐 220181 馬先生 220193 李先生 由TreeMap類實(shí)現(xiàn)的Map集合,鍵對(duì)象升序: 220181 馬先生 220186 王小姐 220193 李先生 由TreeMap類實(shí)現(xiàn)的Map集合,鍵對(duì)象降序: 220193 李先生 220186 王小姐 220181 馬先生 結(jié)束!
TreeMap也可以用一個(gè)簡(jiǎn)單的方法使它按鍵key降序排列: TreeMap<Double, double[]> sortMap = new TreeMap<Double, double[]>(<span style="color:#ff0000;">Collections.reverseOrder()</span>);// 初始化為翻轉(zhuǎn)排序
所以,如果map需要按鍵排序,把鍵-值對(duì)放在TreeMap即可。
map中按值排序則需要重寫Comparator方法,如下的例子: List<Map.Entry<Integer, Double>> entrySet = newArrayList<Map.Entry<Integer, Double>>(map.entrySet());System.out.println("排序前的特征值: " + entrySet);Collections.sort(entrySet,new <span style="color:#ff0000;">Comparator</span><Map.Entry<Integer, Double>>() {public int compare(Entry<Integer, Double> o1,Entry<Integer, Double> o2) {return o2.getValue().compareTo(o1.getValue());//<span style="color:#ff0000;">此處對(duì)象o1和對(duì)象o2的先后順序可決定是按升序還是按降序排序</span>}});
Map常用操作
? ? ? ? ?1) 添加操作:
? ??? ??V put(K key, V value):如果key已存在,在關(guān)聯(lián)后,返回替換前該key對(duì)應(yīng)的value值,如果不存在,則返回null;
? ??? ??void putAll(Map t):將來(lái)自特定映像的所有元素添加給該映射。
? ??2) 刪除操作:
? ??? ??V remove(Object key):從此映射中移除指定鍵的映射關(guān)系(如果存在),不存在則返回null;
? ??? ??void clear() :從此映射中移除所有映射關(guān)系.?
? ??3) 查詢操作:
? ??? ??V get(key): 獲得與關(guān)鍵字key相關(guān)的值,并且返回與關(guān)鍵字key相關(guān)的對(duì)象,如果沒有該關(guān)鍵字,則返回null;判斷key是否存在,可以通過(guò)返回值是否等于null
? ??? ??boolean containsKey(key): 判斷映像中是否存在關(guān)鍵字key;
? ??? ??boolean containsValue(Object value): 判斷映像中是否存在值value;
? ??? ??int size(): 返回當(dāng)前映像中映射的數(shù)量;
? ??? ??boolean isEmpty(): 判斷映像中是否有任何映射.
? ??? ??Collection values():返回映像中所有value值的集,由于值多個(gè),用Collection集合,對(duì)其操作可以使用Collection基本方法.
?
HashMap和HashTable的區(qū)別:
? ?? 1) HashTable:底層是哈希表數(shù)據(jù)結(jié)構(gòu);hash值直接使用對(duì)象的hashCode;不可以存入null鍵和null值;hash數(shù)組默認(rèn)大小是11,增加的方式是?old*2+1;線程同步,在多線程并發(fā)的環(huán)境下,可以直接使用Hashtable;JDK1.0效率低; ? ?2) HashMap:繼承自Dictionary類,底層是哈希表數(shù)據(jù)結(jié)構(gòu);重新計(jì)算hash值;可以存入null鍵和null值;hash數(shù)組的默認(rèn)大小是16,而且一定是2的指數(shù);線程不同步,在多線程并發(fā)的環(huán)境下,要自己增加同步處理;JDK1.2效率高。 ? ? 一般情況下,HashMap能夠比Hashtable工作的更好、更快,主要得益于它的散列算法,以及沒有同步。應(yīng)用程序一般在更高的層面上實(shí) 現(xiàn)了保護(hù)機(jī)制,而不是依賴于這些底層數(shù)據(jù)結(jié)構(gòu)的同步,因此,HashMap能夠在大多應(yīng)用中滿足需要。推薦使用HashMap,如果需要同步,可以使用同步工具類將其轉(zhuǎn)換成支持同步的HashMap。LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí),先得到的記錄肯定是先插入的.也可以在構(gòu)造時(shí)用帶參數(shù),按照應(yīng)用次數(shù)排序。在遍歷的時(shí)候會(huì)比HashMap慢,不過(guò)有種情況例外,當(dāng)HashMap容量很大,實(shí)際數(shù)據(jù)較少時(shí),遍歷起來(lái)可能會(huì)比LinkedHashMap慢,因?yàn)長(zhǎng)inkedHashMap的遍歷速度只和實(shí)際數(shù)據(jù)有關(guān),和容量無(wú)關(guān),而HashMap的遍歷速度和他的容量有關(guān)。
有并發(fā)訪問(wèn)的時(shí)候用ConcurrentHashMap,效率比用鎖的HashMap好 功能上可以,但是畢竟ConcurrentHashMap這種數(shù)據(jù)結(jié)構(gòu)要復(fù)雜些,如果能保證只在單一線程下讀寫,不會(huì)發(fā)生并發(fā)的讀寫,那么就可以試用HashMap。ConcurrentHashMap讀不加鎖?
—————————————————————————————————————————————————————— 寫博經(jīng)驗(yàn)尚淺,請(qǐng)各位多多指教。
總結(jié)
以上是生活随笔為你收集整理的java中的几种泛型类——HashSet、HashMap、TreeSet、TreeMap,遍历map,排序,HashTable比较的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 武器上单打不过谁?
- 下一篇: 社交网络初探——链路预测