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