1. 程式人生 > >java----day19(集合框架)

java----day19(集合框架)

List 介面

  • 它是一個元素存取有序的集合。(例如,存元素的順序是11、22、33。那麼集合中,元素的儲存就是按照11、22、33的順序完成的)。
  • 它是一個帶有索引的集合,通過索引就可以精確的操作集合中的元素(與陣列的索引是一個道理)。
  • 集合中可以有重複的元素,通過元素的equals方法,來比較是否為重複的元素。

List介面的常用子類有:

  1. ArrayList集合
  2. LinkedList集合
  • List介面中常用的方法

  • Iterator的併發修改異常

在list集合迭代元素中,對元素進行判斷,一旦條件滿足就新增一個新元素。程式碼如下

public class IteratorDemo {
	public static void main(String[] args) {
		//建立List集合
		List<String> list = new ArrayList<String>();
		//給集合中新增元素
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		list.add("abc4");
		//迭代集合,當有元素為"abc2"時,集合加入新元素"itcast"
		Iterator<String> it = list.iterator();
		while(it.hasNext()){
			String str = it.next();
			//判斷取出的元素是否是"abc2",是就新增一個新元素
			if("abc2".equals(str)){
				list.add("itcast");// 該操作會導致程式出錯
			}
		}
		System.out.println(list);
	}
}

執行上述程式碼發生了錯誤 java.util.ConcurrentModificationException[L1] 這是什麼原因呢?

在迭代過程中,使用了集合的方法對元素進行操作。導致迭代器並不知道集合中的變化,容易引發資料的不確定性。

併發修改異常解決辦法:在迭代時,不要使用集合的方法操作元素。

那麼想要在迭代時對元素操作咋辦?通過ListIterator迭代器操作元素是可以的,ListIterator的出現,解決了使用Iterator迭代過程中可能會發生的錯誤情況。

List介面下有很多個集合,它們儲存元素所採用的結構方式是不同的,這樣就導致了這些集合有它們各自的特點,供給我們在不同的環境下進行使用。資料儲存的常用結構有:堆疊、佇列、陣列、連結串列

  • 堆疊,後進先出
  • 佇列,先進先出
  • 陣列,查詢快,增刪慢
  • 連結串列,查詢慢,增刪快

ArrayList集合資料儲存的結構是陣列結構。元素增刪慢,查詢快,由於日常開發中使用最多的功能為查詢資料、遍歷資料,所以ArrayList是最常用的集合。

LinkedList集合資料儲存的結構是連結串列結構。方便元素新增、刪除的集合。實際開發中對一個集合元素的新增與刪除經常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。

操作方法:

Vector集合資料儲存的結構是陣列結構,為JDK中最早提供的集合。Vector中提供了一個獨特的取出方式,就是列舉Enumeration,它其實就是早期的迭代器。此介面Enumeration的功能與 Iterator 介面的功能是類似的。Vector集合已被ArrayList替代。列舉Enumeration已被迭代器Iterator替代。

操作方法:

Vector集合對ArrayList集合使用的對比

Set 介面

Collection中可以存放重複元素,也可以不存放重複元素,List中是可以存放重複元素的。Set介面所儲存的元素就是不重複的。

此類實現Set介面,由雜湊表支援(實際上是一個 HashMap集合)。HashSet集合不能保證的迭代順序與元素儲存順序相同。

HashSet集合,採用雜湊表結構儲存資料,保證元素唯一性的方式依賴於:hashCode()與equals()方法

  • 什麼是雜湊表呢?

雜湊表底層使用的也是陣列機制[U1] ,陣列中也存放物件,而這些物件往陣列中存放時的位置比較特殊,當需要把這些物件給陣列中存放時,那麼會根據這些物件的特有資料結合相應的演算法,計算出這個物件在陣列中的位置,然後把這個物件存放在陣列中。而這樣的陣列就稱為雜湊陣列,即就是雜湊表。

當向雜湊表中存放元素時,需要根據元素的特有資料結合相應的演算法,這個演算法其實就是Object類中的hashCode方法。由於任何物件都是Object類的子類,所以任何物件有擁有這個方法。即就是在給雜湊表中存放物件時,會呼叫物件的hashCode方法,算出物件在表中的存放位置,這裡需要注意,如果兩個物件hashCode方法算出結果一樣,這樣現象稱為雜湊衝突,這時會呼叫物件的equals方法,比較這兩個物件是不是同一個物件,如果equals方法返回的是true,那麼就不會把第二個物件存放在雜湊表中,如果返回的是false,就會把這個值存放在雜湊表中。

  • 總結:保證HashSet集合元素的唯一,其實就是根據物件的hashCode和equals方法來決定的。如果我們往集合中存放自定義的物件,那麼保證其唯一,就必須複寫hashCode和equals方法建立屬於當前物件的比較方式。

  1. 給HashSet中儲存JavaAPI中提供的型別元素時,不需要重寫元素的hashCode和equals方法,因為這兩個方法,在JavaAPI的每個類中已經重寫完畢,如String類、Integer類等
  2. 給HashSet中存放自定義型別元素時,需要重寫物件中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一

LinkedHashSet集合保證元素的存入和取出的順序一致

判斷集合唯一的原理

  • ArrayList的contains方法判斷元素是否重複原理

ArrayList的contains方法會使用呼叫方法時,傳入的元素的equals方法依次與集合中的舊元素所比較,從而根據返回的布林值判斷是否有重複元素。此時,當ArrayList存放自定義型別時,由於自定義型別在未重寫equals方法前,判斷是否重複的依據是地址值,所以如果想根據內容判斷是否為重複元素,需要重寫元素的equals方法。

  • HashSet的add/contains等方法判斷元素是否重複原理

Set集合不能存放重複元素,其新增方法在新增時會判斷是否有重複元素,有重複不新增,沒重複則新增。

HashSet集合由於是無序的,其判斷唯一的依據是元素型別的hashCode與equals方法的返回結果。規則如下:

先判斷新元素與集合內已經有的舊元素的HashCode值

  1. 如果不同,說明是不同元素,新增到集合。
  2. 如果相同,再判斷equals比較結果。返回true則相同元素;返回false則不同元素,新增到集合。

所以,使用HashSet儲存自定義型別,如果沒有重寫該類的hashCode與equals方法,則判斷重複時,使用的是地址值,如果想通過內容比較元素是否相同,需要重寫該元素類的hashcode與equals方法。

知識點總結

  • List:(arrylist,linklist)

       它是一個有序的集合(元素存與取的順序相同)

       它可以儲存重複的元素                           

  • Set: (hashset,linkhashset)

        它是一個無序的集合(元素存與取的順序可能不同)

        它不能儲存重複的元素

  • List集合中的特有方法
  1. void add(int index, Object element) 將指定的元素,新增到該集合中的指定位置上
  2. Object get(int index)返回集合中指定位置的元素。
  3. Object remove(int index) 移除列表中指定位置的元素, 返回的是被移除的元素
  4. Object set(int index, Object element)用指定元素替換集合中指定位置的元素,返回值的更新前的元素
  • ArrayList:

         底層資料結構是陣列,查詢快,增刪慢

  • LinkedList:

         底層資料結構是連結串列,查詢慢,增刪快

  • HashSet:

         元素唯一,不能重複

         底層結構是 雜湊表結構

         元素的存與取的順序不能保證一致

         如何保證元素的唯一的?

                   重寫hashCode() 與 equals()方法

  • LinkedHashSet:

         元素唯一不能重複

         底層結構是 雜湊表結構 + 連結串列結構

         元素的存與取的順序一致