什麼是集合
-
Java是一門面向對象的語言,就免不了處理對象
-
爲了方便操作多個對象,那麼我們就得把這多個對象存儲起來
-
想要存儲多個對象(變量),很容易就能想到一個容器
-
集合就是一個放數據的容器(集合類存放的都是對象的引用,而非對象本身)
Collection的由來:
-
集合可以存儲多個元素,但我們對多個元素也有不同的需求
-
多個元素,元素不能重複的
-
多個元素,元素按某種規則排序的
-
針對不同的需求:java就提供了很多集合類,多個集合類的數據結構不同。但是,結構不重要,重要的是能夠存儲東西,能夠判斷,獲取
把集合共性的內容不斷往上提取,最終形成集合的繼承體系---->Collection
數組和集合的區別
-
1:長度的區別
-
數組的長度固定
-
集合的長度可變
-
2:內容不容
-
數組存儲的是同一種類型的元素
-
集合可以存儲不同類型的元素(但是一般我們不這樣幹..)
3:元素的數據類型
-
數組可以存儲基本數據類型,也可以存儲引用類型
-
集合只能存儲引用類型(你存儲的是簡單的int,它會自動裝箱成Integer)
什麼時候使用集合,什麼時候使用數組?
- 數組長度設置過小就造成溢出
- 如果數組的長度設置過大,就造成內存空間浪費(因爲數組的長度是固定的)
爲什麼還要使用數組呢 ?
- 集合的底層都是通過數組來實現的
- 數組的效率更高.例如:IO流 byte[] arr=new byte[1024];就是使用的數組
怎麼選擇集合?
需要唯一嗎?
需要:Set 需要制定順序嗎? 需要:TreeSet 不需要:HashSet 但是想要一個和存儲一致的順序(有序):LinkedHashSet 不需要:List 需要頻繁增加或者刪除元素嗎? 需要:LinkedList 不需要:ArrayList
前綴名就是該集合的數據結構.後綴名就是該集合所屬的體系
看到array:就要想到數組,就要想到查詢快,有角標
看到link:就要想到鏈表,就要想到增刪快,就要想到 add get remove+first last 方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆蓋hashcode方法和equals方法
看到tree:就要想到二叉樹,就要想到排序,就要想到兩個接口Comparable和Comparator
Collection的常見方法
數組轉換成集合
集合轉換成數組
Collection的主要子類List和Set
List常見方法:
List:有順序的collection,並且可以包含重複元素。
├ArrayList
- 數組結構,查詢元素快,添加慢(一般情況下),線程不安全,效率高
└Vector
- 數組結構,查詢元素快,線程安全.效率比ArrayList低
- 現在幾乎不適用
├LinkedList
- 鏈表結構,添加元素快,查詢慢,線程不安全,效率高
細節說明:
LinkedList不同於前面兩種List,它不是基於數組的,所以不受數組性能的限制。
他的每一個節點(Node)都包含了三方面的內容:
1.節點本身的數據: E item;
2.上一個節點的信息:Node<E> prev;
3.下一個節點的信息:Node<E> next;
所以當對LinkedList做添加,刪除動作的時候就不用像基於數組的ArrayList一樣,必須進行大量的數據移動。只要更改nextNode的相關信息就可以實現了,這是LinkedList的優勢。 所以LinkedList集合添加數組效率高
LinkedList的常用方法:
注意事項:LinkedList在內存中不是連續的,ArrayList在內存中是連續的.
List集合的遍歷方式:
方式一:迭代器模式,假設集合名爲(al)
Iterator<String> iterator = al.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
System.out.println(s);
}
擴展:使用ListIterator方式進行遍歷,可以在遍歷的過程中對集合進行增刪改查,只有list有這種方式,使用ListIterator方式還能進行反向遍歷
方式二:增強for
for (String s : al) {
System.out.println(s);
}
方式三:普通for (List特有)
for (int i = 0; i <al.size(); i++) {
System.out.println(al.get(i));
}
List總結:
- 基於Array的List(Vector,ArrayList)適合查詢,而LinkedList 適合添加,刪除操作
- 所有的List中可以有null元素,例如[ tom,null,1 ]
- 所有的List中可以有相同的元素,例如Vector中可以有 [ tom,koo,too,koo ]
- 所有的List中只能容納單個不同類型的對象組成的表(單列集合),而不是Key-Value鍵值對。例如:[ tom,1,c ]
- List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似於數組下 >標)來訪問List中的元素,這類似於Java的數組。
- ArrayList和Vector的區別:ArrayList是非線程安全的,效率高;Vector是基於線程安全的,效率低
- LinkedList:底層基於鏈表實現,鏈表內存是散亂的,每一個元素存儲本身內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢
- List接口有三個常用實現類:LinkedList,ArrayList,Vector
Set :不包含重複元素的Collection。
├HashSet (數據結構是哈希表)
HashSet 怎麼確認唯一?
首先判斷的是兩個元素的哈希值確認元素是否相同,如果相同,再判斷兩個對象的內容是否相同
判斷哈希值是否相同,即是判斷hashCode方法,判斷內容是否相同,即是判斷equals方法
注意:如果哈希值不同,是不需要判斷equals方法的
如果兩個哈希值相同會造成哈希衝突,一般情況下,哈希值都是不會衝突的(這裏不做詳細介紹)
記住:如果元素要存儲到HashSet集合中,必須覆蓋hashCode和equals方法.
一般情況下,如果定義的類會產生很多對象,比如人,學生,書,通常都是覆蓋hashCode和equals方法.建立對象是否相同的依據.
└LinkedhashSet (HashSet的一個子類,一個鏈表)
LinkedhashSet可以保證元素的有序!
└TreesSet (排序,不重複,無索引)
Set的遍歷方式:
方式一:迭代器
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
方式二:增強for
for (String str : set) {
System.out.println(str);
}
Set知識點講解
- 雖然Set同List都實現了Collection接口,但是他們的實現方式卻大不一樣。List基本上都是以Array爲基礎。但是Set則是在 HashMap的基礎上來實現的,這個就是Set和List的根本區別。HashSet的存儲方式是把HashMap中的Key作爲Set的對應存儲項。
- 這個也是爲什麼在Set中不能像在List中一樣有重複的項的根本原因,因爲HashMap的key是不能有重複的。
- HashSet中的元素是不能重複的,如果使用add(Object obj)方法添加已經存在的對象,則會覆蓋前面的對象
- HashSet實現的基礎是Map(HashMap)
- HashSet是一種不包含重複的元素的無序Collection。
- 元素無放入順序,元素不可重複(注意:元素雖然無放入順序,但是元素在set中的位置是有該元素的HashCode決定的,其位置其實是固定的)
集合排序
方式一(讓Bean類實現Comparable接口重寫compareTo方法) 自然排序
返回值 0 , 不存
正數 , 右邊
負數 , 左邊
方式二(自定義一個類實現Comparator接口重寫compare方法,通過構造方法傳入自定義類的對象)比較器排序
比如:String ,Integer 對象 ,實現特殊的排序需求, 需要傳遞比較器的子類對象 .