HashSet
HashSet<E>泛型類在數據組織上類似于數學上的集合,可以進行“交”、“并”、“差”等運算。HashSet<E>泛型類創建的對象稱為集合,如:? ? HashSet<E> set = ?HashSet<String>();? ? 那么set就是一個可以存儲string類型數據的集合,set可以調用add(String s)方法將string類型的數據添加到集合中。添加到集合中的數據稱為集合的元素。集合不允許有相同的元素。也就是說,如果b已經是集合中的元素,那么執行add(b)的操作是無效的。集合對象的初始容量是16字節,裝載因子是0.75。也就是說,如果集合添加的元素超過總容量的75%是,集合的容量將增加1倍。相關運算:并運算:boolean addAll(HashSet);交運算:boolean retainAll(HashSet);差運算:boolean remainAll(HashSet);參數指定的集合必須與當前集合是同種類型的集合,否則上述方法返回的類型是false。HashSet<E>泛型類實現了泛型接口Set<E>,而Set<E>接口是Collection<E>接口的子接口。HashSet<E>類中的絕大部分方法都是接口方法的實現。編程時,可以使用接口回調技術,即把HashSet<E>對象的引用賦值給Collection<E>接口變量或Set<E>接口變量,那么接口就可以調用類實現的接口方法。
HashMap
HashMap<K,V>對象成為散列映射對象。散列映射用于存儲鍵-值數據對,允許把任何數量的鍵-值數據存儲在一起。鍵不可以可重復。如果出現兩個數據項的鍵相同,那么先前散列映射中的鍵-值對將被替換。散列映射在它需要更多存儲容量是會自動增大容量。例如,如果散列映射的裝載因子是75%時,它就自動把容量增加到原始容量的2倍。對于數組和鏈表這兩種數據結構,如果要查找它們存儲的某個特定的元素卻不知道它們的位置,就需要從頭開始訪問元素知道找到匹配的為止;如果數據結構中包含很多元素,就會浪費時間。這時最好使用散列映射來存儲要找的數據,以便檢索時可以減少檢索的開銷。HashMap<K,V>泛型類創建的對象稱為散列映射,如:
? ? ?HashMap<K,V> hash = HashMap<String,Student>();? ? ?那么,hash就可以存儲鍵-值對數據,其中的鍵必須是一個String對象,鍵對應的值必須是Student對象。hash可以調用public V put(K key, V value)方法將鍵-值對存儲在散列映射中,同時返回鍵所對應的值。? ?遍歷散列映射的方法有如下四種:HashMap<E>泛型類是實現泛型接口Map<E>。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);} }
TreeSet
TreeSet<E>類是實現Set接口的類。
TreeSet<E>泛型類創建的對象稱為樹集,如:
? ? ?TreeSet<Student> tree = TreeSet<Student>();? ? ?那么tree就是一個可以存儲Student對象的集合,tree可以調用add(Student s)方法將Student對象添加到樹集中。樹集采用樹結構存儲數據,樹集節點的排列和鏈表不同,不按添加的先后順序順序排列。樹集采用add()方法增加節點,節點會按其存放的數據的“大小”順序一層一層地依次排序,同一層的節點按“大小”順序遞增排列,下一層的比上一層的小。樹集是一個有序集合。TreeMap
TreeMap類實現了Map接口,TreeSet類提供了按排序順序存儲鍵-值對的有效手段。TreeMap保證它的元素按key升序排列。構造函數有2種:? ?TreeMap<K,V>()按照關鍵字key的大小順序來對鍵-值對進行升序排序,key的順序是按其字符串表示的字典順序。? ?TreeMap<K,V>(Comparator<K> comp)關鍵字key的大小順序按照Comparator接口規定的大小順序對樹映射中的鍵-值對進行排序,即可以升序,也可以降序,取決于里面重寫的方法。? ?下面是一個排序的例子: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類實現的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類實現的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類實現的Map集合,鍵對象降序:");TreeMap<Number, Person> treeMap2 = new TreeMap<Number, Person>(Collections.reverseOrder());// 初始化為反轉排序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("結束!");} }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;} }
? ? ?輸出結果為:開始: 由HashMap類實現的Map集合,無序: 220186 王小姐 220181 馬先生 220193 李先生 由TreeMap類實現的Map集合,鍵對象升序: 220181 馬先生 220186 王小姐 220193 李先生 由TreeMap類實現的Map集合,鍵對象降序: 220193 李先生 220186 王小姐 220181 馬先生 結束!
TreeMap也可以用一個簡單的方法使它按鍵key降序排列:TreeMap<Double, double[]> sortMap = new TreeMap<Double, double[]>(<span style="color:#ff0000;">Collections.reverseOrder()</span>);// 初始化為翻轉排序
所以,如果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已存在,在關聯后,返回替換前該key對應的value值,如果不存在,則返回null;
? ??? ??void putAll(Map t):將來自特定映像的所有元素添加給該映射。
? ??2) 刪除操作:
? ??? ??V remove(Object key):從此映射中移除指定鍵的映射關系(如果存在),不存在則返回null;
? ??? ??void clear() :從此映射中移除所有映射關系.?
? ??3) 查詢操作:
? ??? ??V get(key): 獲得與關鍵字key相關的值,并且返回與關鍵字key相關的對象,如果沒有該關鍵字,則返回null;判斷key是否存在,可以通過返回值是否等于null
? ??? ??boolean containsKey(key): 判斷映像中是否存在關鍵字key;
? ??? ??boolean containsValue(Object value): 判斷映像中是否存在值value;
? ??? ??int size(): 返回當前映像中映射的數量;
? ??? ??boolean isEmpty(): 判斷映像中是否有任何映射.
? ??? ??Collection values():返回映像中所有value值的集,由于值多個,用Collection集合,對其操作可以使用Collection基本方法.?
HashMap和HashTable的區別:
? ?? 1) HashTable:底層是哈希表數據結構;hash值直接使用對象的hashCode;不可以存入null鍵和null值;hash數組默認大小是11,增加的方式是?old*2+1;線程同步,在多線程并發的環境下,可以直接使用Hashtable;JDK1.0效率低;? ?2) HashMap:繼承自Dictionary類,底層是哈希表數據結構;重新計算hash值;可以存入null鍵和null值;hash數組的默認大小是16,而且一定是2的指數;線程不同步,在多線程并發的環境下,要自己增加同步處理;JDK1.2效率高。? ? 一般情況下,HashMap能夠比Hashtable工作的更好、更快,主要得益于它的散列算法,以及沒有同步。應用程序一般在更高的層面上實 現了保護機制,而不是依賴于這些底層數據結構的同步,因此,HashMap能夠在大多應用中滿足需要。推薦使用HashMap,如果需要同步,可以使用同步工具類將其轉換成支持同步的HashMap。
LinkedHashMap保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時,先得到的記錄肯定是先插入的.也可以在構造時用帶參數,按照應用次數排序。在遍歷的時候會比HashMap慢,不過有種情況例外,當HashMap容量很大,實際數據較少時,遍歷起來可能會比LinkedHashMap慢,因為LinkedHashMap的遍歷速度只和實際數據有關,和容量無關,而HashMap的遍歷速度和他的容量有關。
有并發訪問的時候用ConcurrentHashMap,效率比用鎖的HashMap好 功能上可以,但是畢竟ConcurrentHashMap這種數據結構要復雜些,如果能保證只在單一線程下讀寫,不會發生并發的讀寫,那么就可以試用HashMap。ConcurrentHashMap讀不加鎖?
——————————————————————————————————————————————————————寫博經驗尚淺,請各位多多指教。