HashSet 循環java
//能夠爲null HashSet<Object> hashSet =new HashSet<Object>(); hashSet.add(1); hashSet.add("wsss"); hashSet.add(null); for (Object s : hashSet) { System.out.println(s); } System.out.println("-----------"); Iterator iterator = hashSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("-----------"); Iterator itor =hashSet.iterator(); for (Object o : hashSet) { if(o instanceof Integer){ Integer n =(Integer)o; System.out.println(n); }else if(o instanceof String){ String str=(String)o; System.out.println(str); }else{ System.out.println(o); } }
HashMap循環
//能夠爲null HashMap<String,String> hashMap = new HashMap<String,String>(); hashMap.put("1","zhangsan"); hashMap.put("4","lisi"); hashMap.put("7","wangwu"); hashMap.put(null,null); Iterator<Map.Entry<String,String>> iterator =hashMap.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<String,String> o =iterator.next(); System.out.println(o.getKey()+" "+o.getValue()); } System.out.println("-----------"); for (String key : hashMap.keySet()) { System.out.println(key+" "+hashMap.get(key)); } System.out.println("-----------"); for (Map.Entry<String, String> entry : hashMap.entrySet()) { System.out.println(entry.getKey()+" "+entry.getValue()); } System.out.println("-----------"); //遍歷全部value for (String v : hashMap.values()) { System.out.println(v); }
Hashtable循環
//不能爲null Hashtable<String,String> hashtable=new Hashtable<String,String>(); hashtable.put("1","zhangsan"); hashtable.put("2","lisi"); hashtable.put("3","wangwu"); for (String key:hashtable.keySet()){ System.out.println(key +" "+hashtable.get(key)); } System.out.println("-----------"); Iterator<Map.Entry<String,String>> iterator = hashtable.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<String,String> itr =iterator.next(); System.out.println(itr.getKey()+" "+itr.getValue()); } System.out.println("-----------"); for (Map.Entry<String, String> entry : hashtable.entrySet()) { System.out.println(entry.getKey()+" "+entry.getValue()); }
TreeSet 循環算法
//不能爲null TreeSet<String> treeSet =new TreeSet<String>(); treeSet.add("zhangsan"); treeSet.add("ain"); treeSet.add("wangwu"); Iterator iter = treeSet.iterator(); while (iter.hasNext()){ System.out.println(iter.next()); }
區別數組
一、HashSet實現的是Set接口,HashMap實現的是map接口
二、HashSet存儲的是key,,其實更準確的說是存儲一個(key,o),o是HashSet裏的一個Object型的成員變量;而HashMap存儲的是(key-value);Hashtable竄出的是(key-value);
三、Hashtable中,key和value都不容許出現null值,HashSet、HashMap均可覺得null值
四、Hashtable中的方法是同步的,而HashMap、HashSet中的方法在缺省狀況下是非同步的。
六、添加元素的時候HashMap、Hashtable使用的是put(key,value),HashSet使用的是add(key);安全
-------------------
TreeSet是一個有序的集合,不容許放入null值,HashSet中的數據是無序的,
TreeSet採用的數據結構是紅黑樹,HashSet底層用的是哈希表數據結構
----------------多線程
TreeMap 是一個有序的key-value集合,它是經過紅黑樹實現的。
TreeMap 繼承於AbstractMap,因此它是一個Map,即一個key-value集合。
TreeMap 實現了NavigableMap接口,意味着它支持一系列的導航方法。好比返回有序的key集合。
TreeMap 實現了Cloneable接口,意味着它能被克隆。
TreeMap 實現了java.io.Serializable接口,意味着它支持序列化。
TreeMap基於紅黑樹(Red-Black tree)實現。該映射根據其鍵的天然順序進行排序,或者根據建立映射時提供的 Comparator 進行排序,具體取決於使用的構造方法。
TreeMap的基本操做 containsKey、get、put 和 remove 的時間複雜度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。app
TreeSet和TreeMap的關係性能
與HashSet徹底相似,TreeSet裏面絕大部分方法都市直接調用TreeMap方法來實現的。優化
相同點:spa
- TreeMap和TreeSet都是非同步集合,所以他們不能在多線程之間共享,不過可使用方法Collections.synchroinzedMap()來實現同步
- 運行速度都要比Hash集合慢,他們內部對元素的操做時間複雜度爲O(logN),而HashMap/HashSet則爲O(1)。
- TreeMap和TreeSet都是有序的集合,也就是說他們存儲的值都是拍好序的。
不一樣點:
- 最主要的區別就是TreeSet和TreeMap分別實現Set和Map接口
- TreeSet只存儲一個對象,而TreeMap存儲兩個對象Key和Value(僅僅key對象有序)
- TreeSet中不能有重複對象,而TreeMap中能夠存在
- TreeMap的底層採用紅黑樹的實現,完成數據有序的插入,排序。
什麼是HashMap?
HashMap是一個用於存儲Key-Value鍵值對的集合,每個鍵值對也叫作Entry。這些個鍵值對(Entry)分散存儲在一個數組當中,這個數組就是HashMap的主幹。
HashMap數組每個元素的初始值都是Null。
HashMap是非synchronized;HashMap很快
HashMap是在bucket中儲存鍵對象和值對象,做爲Map.Entry
HashMap的初始長度是16,而且每次自動擴展或手動初始化時,長度必須是2的冪。
java7:數組+鏈表
java8:數組+鏈表+紅黑樹
java8對hashMap作了什麼優化?
ava7中 hashMap每一個桶中放置的是鏈表,這樣當hash碰撞嚴重時,會致使個別位置鏈表長度過長,從而影響性能。
java8中,HashMap 每一個桶中當鏈表長度超過8以後,會將鏈表轉換成紅黑樹,從而提高增刪改查的速度。
HashMap安排的初始長度,爲何?
初始長度是 16,每次擴展或者是手動初始化,長度必須是 2的冪。
由於: index = HashCode(Key) & (length - 1), 若是 length是 2的 冪的話,則 length - 1就是 全是 1的二進制數,好比 16 - 1 = 1111,這樣至關因而 坐落在長度爲 length的hashMap上的位置只和 HashCode的後四位有關,這隻要給出的HashCode算法自己分佈均勻,算出的index就是分佈均勻的。
由於HashMap的key是int類型,因此最大值是2^31次方,可是查看源碼,當到達 2^30次方,即 MAXIMUM_CAPACITY,以後,便再也不進行擴容。
你知道HashMap的get()方法的工做原理嗎?
HashMap是基於hashing的原理,咱們使用put(key, value)存儲對象到HashMap中,使用get(key)從HashMap中獲取對象。當咱們給put()方法傳遞鍵和值時,咱們先對鍵調用hashCode()方法,返回的hashCode用於找到bucket位置來儲存Entry對象.
使用Get方法根據Key來查找Value的時候,HashMap會使用鍵對象的hashcode找到bucket位置
當兩個對象的hashcode相同會發生什麼?
由於hashcode相同,因此它們的bucket位置相同,‘碰撞’會發生。由於HashMap使用LinkedList存儲對象,這個Entry(包含有鍵值對的Map.Entry對象)會存儲在LinkedList中
若是兩個鍵的hashcode相同,你如何獲取值對象?
當咱們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,找到bucket位置以後,會調用keys.equals()方法去找到LinkedList中正確的節點,最終找到要找的值對象
若是HashMap的大小超過了負載因子(load factor)定義的容量,怎麼辦?
默認的負載因子大小爲0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類同樣,將會建立原來HashMap大小的兩倍的bucket數組,來從新調整map的大小,並將原來的對象放入新的bucket數組中。這個過程叫做(再散列)rehashing,由於它調用hash方法找到新的bucket位置。
可使用自定義的對象做爲鍵嗎?
可使用任何對象做爲鍵,只要它遵照了equals()和hashCode()方法的定義規則,而且當對象插入到Map中以後將不會再改變了。若是這個自定義對象時不可變的,那麼它已經知足了做爲鍵的條件,由於當它建立以後就已經不能改變了。
可使用CocurrentHashMap來代替HashTable嗎?
HashTable是synchronized的,可是ConcurrentHashMap同步性能更好,由於它僅僅根據同步級別對map的一部分進行上鎖。ConcurrentHashMap固然能夠代替HashTable,可是HashTable提供更強的線程安全性。
爲何String, Interger這樣的wrapper類適合做爲鍵? 由於String是不可變的,也是final的,並且已經重寫了equals()和hashCode()方法了。其餘的wrapper類也有這個特色。不可變性是必要的,由於爲了要計算hashCode(),就要防止鍵值改變,若是鍵值在放入時和獲取時返回不一樣的hashcode的話,那麼就不能從HashMap中找到你想要的對象。不可變性還有其餘的優勢如線程安全。若是你能夠僅僅經過將某個field聲明成final就能保證hashCode是不變的,那麼請這麼作吧。由於獲取對象的時候要用到equals()和hashCode()方法,那麼鍵對象正確的重寫這兩個方法是很是重要的。若是兩個不相等的對象返回不一樣的hashcode的話,那麼碰撞的概率就會小些,這樣就能提升HashMap的性能。