Java 集合

 

Java集合:

  Java集合主要負責保存、承裝其餘數據,所以集合類也被稱爲容器類;java

  Java集合大體可分爲Set、List、Queue、Map四種,其中Set表明無序,不可重複的集合;List表明有序,可重複的集合;Map則表明具備映射關係的集合,Java5後又增長了Queue體系集合,表明一種隊列集合的實現;算法

  全部的集合類都在java.util包下;Java5還在java.util.concurrent包下提供了一些多線程支持的集合類數組

Java集合與數組的區別:

  數組長度不可變化,一旦在初始化的時候指定了數組長度,這個數組長度就是不可變的,若是須要保存數量變化的數據,數組就無能爲力了;安全

  數組沒法保存具備映射關係的數據,如成績表:語文-70,數學-80;多線程

  數組元素既能夠是基本類型的值,也能夠是對象(實際上是對象的引用變量),而集合中只能保存對象(實際上是對象的引用變量)框架

Java集合體系:

  Java集合類主要由兩個接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,這兩個接口又包含了一些子接口或實現類Collection體系:工具

  Set和List接口是Collection接口派生的兩個子接口,分別表明了無序集合和有序集合性能

  Queue是Java提供的隊列實現this

Map體系:spa

  Map接口有衆多實現類,這些實現類在功能、用法上存在必定的差別,但他們都有一個功能特徵:Map保存的每項數據都是key-value對

Set集合之HashSet:

  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來快速訪問元素

 

 Set集合之LinkedHashSet:

  LinkedHashSet是HashSet的子類。也是根據元素的hashCode值肯定元素的存儲位置,同時使用鏈表維護元素的次序,這樣是的元素看起來是以插入的順序保存的

    LinkedHashSet須要維護元素插入的順序,所以性能略低於HashSet的性能,但在迭代訪問Set所有元素時將有很好的性能,由於他用鏈表來維護內部順序

 List集合之ArrayList:

  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

List集合之Vector:

  ArrayList和Vector都是基於數組實現的List類,因此ArrayList和Vector類封裝了一個容許再分配的Object[]數組;

  ArrayList是線程不安全的,當多個線程訪問同一個ArrayList集合時,若是有一個線程修改了ArrayList集合,則程序必須手動保證該集合的同步性,可是Collections工具類,會將一個ArrayList變爲線程安全的

 List集合之LinkedList:

  LinkedList能夠根據索引來隨機訪問集合中的元素;

  除此以外,LinkedList還實現了Deque接口,能夠被當成雙端隊列使用,所以,既能夠被當成棧來用,也能夠當成隊列使用;

ArrayList和LinkedList的區別:
 
  LinkedList與ArrayList、ArrayDeque的實現機制不一樣,ArrayList和ArrayDeque內部使用數組的形式來保存集合中的元素,所以隨機訪問集合元素時有較好的性能;
  而LinkedList內部使用連標的形式來保存集合中的元素,所以隨機訪問性能較差,但在插入、刪除時性能比較出色

 Map集合之HashMap:

   若是將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; }

Map集合之Hashtable:

  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變爲線程安全的

Java集合遍歷的方法:

  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工具類: 

 操做數組的工具類
 工具類彙總的方法基本都是靜態的

 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工具類:

操做集合的工具類

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):
  給定的數組長度大於集合中對象的個數,則使用給定的數組
  給定的數組長度小於集合中對象的個數,會建立一個新的數組織,數組長度和集合對象個數相同
  給定的數組長度和集合中對象個數相同
  集合轉數組能夠防止數據被隨意的添加或刪除,由於數組長度是固定的
相關文章
相關標籤/搜索