Java集合主要負責保存、承裝其餘數據,所以集合類也被稱爲容器類;java
Java集合大體可分爲Set、List、Queue、Map四種,其中Set表明無序,不可重複的集合;List表明有序,可重複的集合;Map則表明具備映射關係的集合,Java5後又增長了Queue體系集合,表明一種隊列集合的實現;算法
全部的集合類都在java.util包下;Java5還在java.util.concurrent包下提供了一些多線程支持的集合類數組
數組長度不可變化,一旦在初始化的時候指定了數組長度,這個數組長度就是不可變的,若是須要保存數量變化的數據,數組就無能爲力了;安全
數組沒法保存具備映射關係的數據,如成績表:語文-70,數學-80;多線程
數組元素既能夠是基本類型的值,也能夠是對象(實際上是對象的引用變量),而集合中只能保存對象(實際上是對象的引用變量)框架
Java集合類主要由兩個接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,這兩個接口又包含了一些子接口或實現類Collection體系:工具
Set和List接口是Collection接口派生的兩個子接口,分別表明了無序集合和有序集合性能
Queue是Java提供的隊列實現this
Map體系:spa
Map接口有衆多實現類,這些實現類在功能、用法上存在必定的差別,但他們都有一個功能特徵:Map保存的每項數據都是key-value對
HashSet按照Hash算法存儲集合的元素,所以具備很好的存取和查找性能;
當向HashSet集合中存入一個元素時,HashSet會調用該對象的hashCode()方法來獲得該對象的hashCode值,而後根據這個hashCode值決定該對象在HashSet中存儲的位置;若是有兩個元素經過equals()方法比較返回true,但它們的hashCode()方法返回值不等,HashSet會把他們存儲在不一樣的位置,依然能夠添加成功;
也就是說,HashSet集合判斷兩個元素相等的標準是兩個對象經過equals()方法比較相等,而且兩個對象的hashCode()方法返回值也相等
特色:
1 不能保證元素的排列順序
2 HashSet不是同步的,若是多線程同時訪問一個HashSet,假設有兩個或兩個以上的線程同時修改了HashSet集合時,必須經過代碼保證同步
3 集合元素能夠爲null
hashCode()方法重寫的基本規則:
1 程序運行過程當中,同一對對象屢次調用hashCode()應返回相同的值
2 對象中用做equals()方法比較標準的實例變量,都應該用於計算hashCode
3 若是須要把某個類的對象保存到HashSet集合中,重寫這個類的equals()方法和hashCode()方法時,應該儘可能保證兩個對象經過equals()方法比較返回true時,他們的hashCode()方法返回值也相等
若是兩個對象經過equals()方法返回true,但這兩個對象的hashCode()方法返回不一樣的hashCode時,這將致使HashSet會把這兩個對象保存在Hash表的不一樣位置,從而使兩個對象均可以添加成功,這就與Set集合的規則衝突了
若是兩個對象的hashCode()方法返回值相同,但他們經過equals方法比較返回false時更麻煩:
由於兩個對象的hashCode()值相同,HashSet試圖將他們保存在同一位置,但又不行(不然只會剩下一個對象),因此實際上會在這個位置用鏈式結構來保存多個對象;
而HashSet訪問集合元素時也是根據元素的hashCode值來快速定位的,若是HashCode中兩個以上的元素具備相同的hashCode,將會致使性能降低
hashCode()方法是否是對HashSet十分重要?
hash算法的功能是,他能保證快速查找的被檢索的對象,hash算法的價值在與速度;當須要查詢集合中的某個元素時,hash算法能夠直接根據元素的hashCode計算出元素的存儲位置,從而快速定位元素
爲何不直接使用數組,還須要HashSet?
數組元素的索引是連續的。並且數組的長度是固定的,沒法自由增長數組的長度;而HashSet使用hashCode計算元素的存儲位置,從而能夠自由增長HashSet的長度,而且能夠根據元素的hashCode來快速訪問元素
LinkedHashSet是HashSet的子類。也是根據元素的hashCode值肯定元素的存儲位置,同時使用鏈表維護元素的次序,這樣是的元素看起來是以插入的順序保存的
LinkedHashSet須要維護元素插入的順序,所以性能略低於HashSet的性能,但在迭代訪問Set所有元素時將有很好的性能,由於他用鏈表來維護內部順序
List判斷兩個對象相等的標準是equals()方法比較返回true便可;
List增長了sort()和erplaceAll()兩個經常使用的默認方法,其中,sort()方法須要一個Comparator對象來控制元素排序
ArrayList的底層實現:
爲何ArrayList能夠變長?
ArrayList和Vector都是基於數組實現的List類,因此ArrayList和Vector類封裝了一個動態的、可再分配的Object[]數組;
ArrayList或Vector對象使用initialCapacity參數來設置該數組的長度,當向ArrayList或Vector中添加元素超出了該數組的長度後,他們的initialCapaticy會自動增長;
一般,咱們不須要關心initiaCapaticy,但若是向ArrayList或Vector集合中添加大量元素時,可以使用ensureCapaticy(int minCapaticy)方法一次性的增長initialCapaticy,這能夠減小再分配的次數,提升性能
若是開始就知道ArrayList或Vector集合須要保存多少元素,則能夠在建立它們時就指定initialCapaticy大小
若是建立空的ArrayList或Vector集合時不指定initialCapaticy參數,則Object[]的長度默認爲10
ArrayList和Vector都是基於數組實現的List類,因此ArrayList和Vector類封裝了一個容許再分配的Object[]數組;
ArrayList是線程不安全的,當多個線程訪問同一個ArrayList集合時,若是有一個線程修改了ArrayList集合,則程序必須手動保證該集合的同步性,可是Collections工具類,會將一個ArrayList變爲線程安全的
LinkedList能夠根據索引來隨機訪問集合中的元素;
除此以外,LinkedList還實現了Deque接口,能夠被當成雙端隊列使用,所以,既能夠被當成棧來用,也能夠當成隊列使用;
ArrayList和LinkedList的區別:
LinkedList與ArrayList、ArrayDeque的實現機制不一樣,ArrayList和ArrayDeque內部使用數組的形式來保存集合中的元素,所以隨機訪問集合元素時有較好的性能;
而LinkedList內部使用連標的形式來保存集合中的元素,所以隨機訪問性能較差,但在插入、刪除時性能比較出色
若是將Map裏的全部value放在一塊兒看,很是相似於一個List:
元素與元素之間能夠重複;
每一個元素能夠根據索引來查找,只是Map中的索引再也不使用整數值,而是以另外一個對象做爲索引:若是要從List集合中取出元素,則須要提供元素的數字索引;若是要從Map中取出元素,則須要提供元素的key索引,所以,Map有時也被稱爲字典或關聯數組
如何保證鍵不能重複(和HashSet相同)int hashCode()
Boolean equals(Object obj)
public int hashCode() { return name.hashCode()+age*33; } public boolean equals(Object obj) { if(!obj instanceof Student) throw new ClassCastException("類型轉換異常"); Student stu = (Student)obj; return this.name.equals(stu.name) && this.age==stu.age; }
HashMap和Hashtable都是Map接口的典型實現類,他們之間的關係相似於ArrayList和Vector的關係;
HashTable是一個古老的Map實現類,出現的時候Java尚未提供Map接口,因此它包含了兩個繁瑣的方法:elements()和keys();
Java8改進了HashMap的實現,使用HashMap存在key衝突時依然具備較好的性能
HashMap與Hashtable的區別:
Hashtable是一個線程安全的Map實現,而HashMap是線程不安全的實現,因此HashMap比Hashtable的性能高一點;但若是有多個線程訪問同一個Map對象時,使用Hashtable實現類會更好;
Hashtable不容許使用null做爲key和value,可是若是試圖將null值放入Hashtable中,將會引起NullPointerException異常;可是HashMap可使用null做爲key或value;
與Vector相似的是,儘可能少用Hashtable,即便須要建立線程安全的Map實現類,也無須使用Hashtable實現類,能夠經過Collections工具類把HashMap變爲線程安全的
Iterator:
Set<K> keyset()
獲得全部鍵的集合存儲到一個Set中,並返回一個Set集合,由於Set有迭代器,因此使用迭代器迭代,每次迭代出一個鍵,再根據鍵獲取值
Set<String> keys = map.keySet(); Iterator<String> ite = keys.iterator(); while(ite.hasNext()) { String key = ite.next(); String value = map.get(key); System.out.println(key + "=" + value); }
****************************************************** Set<Map.Entry<K, V>> entrySet()
Map.Entry<K, V>映射關係類型 Entry是定義在Map中的一個靜態接口,有了集合中的鍵值對,纔會存在映射關係,因此映射關係是對集合內部事物的描述,因此定義在Map內部 獲得每一個鍵值對對應的映射關係類型的值,存到Set集合彙總,並返回該集合,由於Set有迭代器,每次迭代出來的是一個映射類型的值,從這個映射關係類型的值中,便可以獲得鍵,也能夠獲得值 Set<Map.Entry<String, String>> entry = map.entrySet(); Iterator<Map.Entry<String, String>> ite = keys.iterator(); while(ite.hasNext()) { Map.Entry<String, String> en = ite.next(); String key = en.getKey(); String value = en.getValue(); System.out.println(key + "=" + value); }
foreach:
for(數據類型 變量名: 被遍歷的數組或Collection集合) { //使用foreach循環迭代訪問集合元素時,該集合不能被改變,不然會引起ConcurrentModificationException異常 } HashMap<String, String> map = new HashMap<>(); map.put("001", "aaa"); map.put("002", "bbb"); for(String key: map.keySet()) { String value = map.get(key); System.out.println(key + "= " + value); } 或: for(Map.entry<String, String> en: map.entrySet()) { String key = en.getKey(); String value = map.getValue(); System.out.println(key + "= " + value); }
操做數組的工具類
工具類彙總的方法基本都是靜態的
Arrays.toString(arr):把數組中的內容轉成字符串
Arrays.asList(arr):數組轉集合
數組轉成的集合不能進行添加和刪除 由於數組的長度是固定的 數組只能存儲對象
爲何要數組轉集合?
集合的方法多:
迭代:
Iterator<String> ite = list.iterator(); while(ite.hasNext()) {
System.out.println(ite.next()); }
int [] arr = {1, 2, 3}; List list = Aarrays.asList(arr); System.out.print(list.size());
爲何list長度爲1? 數組只能存儲對象arr是個int數組 集合存儲的是引用類型的對象 由於數組是引用類型的
List將arr總體做爲一個對象存入集合 因此長度爲1
操做集合的工具類 Collections.sort():排序 按照集合中對象所屬的類自身具有的比較方式進行排序的 即int compareTo()方法 按照自定義的比較方式對集合中的對象 實現Comparator<String>接口 重寫compare方法 傳入實現接口的類的對象 Collections.reverseOrder():翻轉輸出結果 沒有參數則翻轉默認的比較方式
如何獲得和比較值相反的比較方式?
Comparator com = Collections.reverseOrder(new ComByLength()); Collections.sort(list, com); System.out.println(list);
本身實現max? public static <E extends Compare<? super E>> getMax(Clooection<? extends E> col) { Iterator<? extends E> ite = col.iterator(); E obj = ite.next();//獲得集合中的一個對象 while(ite.hasNext()) { E object = ite.next(); int num = obj.compareTo(object); if(num < 0) obj = object; } return obj; }
Collections.toArray(T[] a):
給定的數組長度大於集合中對象的個數,則使用給定的數組
給定的數組長度小於集合中對象的個數,會建立一個新的數組織,數組長度和集合對象個數相同
給定的數組長度和集合中對象個數相同
集合轉數組能夠防止數據被隨意的添加或刪除,由於數組長度是固定的