Java之集合初探(一)
一、集合概述、區別
集合是一種容器,陣列也是一種容器
在Java程式設計中,裝各種各樣的物件(引用型別)的叫做容器。
為什麼出現集合類?
面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多個物件的操作,Java就提供了集合類。
陣列和集合類同是容器,有何不同?
A:長度區別 陣列的長度固定 集合長度可變 B:內容不同 陣列儲存的是同一種類型的元素 而集合可以儲存不同型別的元素 C:元素的資料型別問題 陣列可以儲存基本資料型別,也可以儲存引用資料型別 集合只能儲存引用型別
集合類的特點
集合只用於儲存物件,集合長度是可變的,集合可以儲存不同型別的物件。
如果我們用陣列來製作一個簡單的容器,可以儲存資料改變大小
//自定義的容器 package util; import java.lang.reflect.Array; import java.util.Arrays; public class Myarr { private Object[] obj; private int size;//代表陣列中有效的數量 public Myarr(){ obj=new Object[10]; size=0; } public int Size(){ return this.size; } public boolean add(Object o){//可以新增各種型別 //因為陣列的長度是固定的,首先判斷裝滿否 if(size<obj.length){//有效長度小於陣列長度,沒裝滿 obj[size]=o; }else{ Object[] os=Arrays.copyOf(obj, size+1); os[size]=o; obj=os; } size++; if(size==obj.length){ return true; } return false; } public String toString(){ Object[] onew=new Object[size]; for(int i=0;i<size;i++){ onew[i]=obj[i]; } return Arrays.toString(onew); } }
//主方法 package test; import util.Myarr; public class Test { public static void main(String[] args) { // 新增小於10的情況 Myarr ma=new Myarr(); ma.add(56); ma.add("so"); ma.add(5.653); System.out.println(ma.Size()); System.out.println(ma); //新增大於10的情況 Myarr ma1=new Myarr(); ma1.add(56); ma1.add("so"); ma1.add(5.653); ma1.add(56); ma1.add("so"); ma1.add(5.653); ma1.add(56); ma1.add("so"); ma1.add(5.653); ma1.add(56); ma1.add("so"); ma1.add(5.653); System.out.println(ma1.Size()); System.out.println(ma1); } }
二、不同的集合類
集合是儲存多個元的,由於儲存多個元素我們也是有不同需求的:比如,我要這多個元素中不能有相同的元素,再比如,我要這多個元素按照某種規則排序一下。針對不同的需求,Java就提供了不同的集合類。 這多個集合類的資料結構不同,結構不同不重要的,重要的是你要能夠儲存東西,並且還要能夠使用這些東西,比如說判斷,獲取等。 既然這樣,那麼,這多個集合類是有共性的內容的,我們把這些集合類的共性內容不斷的向上提取,最終就能形成集合的繼承體系結構
Collection:是集合的頂層介面,它的子體系有重複的,有唯一的,有有序的,有無序的。
Collection List---(有順序, 可以重複)---下標
(這裡判斷重複的標準是可以互相equals(引用型別))
LinkedList(基於連結串列)---(改快,查慢)
*ArrayList(基於陣列)---(改慢,查快)
Set---(沒有順序, 不可以重複)
*HashSet(基於hash碼錶)(必須重寫hashCode()方法)
TreeSet(基於二叉樹---資料結構)
Map(以鍵值對的方式存在)(鍵不能重複)
Map<Person.hashCode(), int>
*HashMap
TreeMap
Comparable(一個方法(comparaTo))
Iterator(迴圈遍歷, 3個方法)
返回值boolean hasNext()集合裡有沒有下一個
返回值Object next()返回下一個物件的例項
remove()
大致如下
while(hasNext()) { next() }
注意:
介面不可以直接new例項化,new後面只能是他的子類,Collection裡沒有方法體
Collection的功能概述:
1:新增功能 boolean add(Object obj):新增一個元素 boolean addAll(Collection c):新增一個集合的元素 2:刪除功能 void clear():移除所有元素 boolean remove(Object o):移除一個元素 boolean removeAll(Collection c):移除一個集合的元素(是一個還是所有) 3:判斷功能 boolean contains(Object o):判斷集合中是否包含指定的元素 boolean containsAll(Collection c):判斷集合中是否包含指定的集合元素(是一個還是所有) boolean isEmpty():判斷集合是否為空 4:獲取功能 Iterator<E> iterator()(重點) 5:長度功能 int size():元素的個數 面試題:陣列有沒有length()方法呢?字串有沒有length()方法呢?集合有沒有length()方法呢? 6:交集功能 boolean retainAll(Collection c):兩個集合都有的元素?思考元素去哪了,返回的boolean又是什麼意思呢? 7:把集合轉換為陣列 Object[] toArray()
Java中集合主要分為三類
- Set(集)
- List(列表)
- Map(對映)
List介面(列表):
List的特徵是其元素以線性方式儲存,集合中可以存放重複物件。
List介面主要實現類包括:
- ArrayList() : 代表長度可以改變得陣列。可以對元素進行隨機的訪問,向ArrayList()中插入與刪除元素的速度慢。 API中介紹初始容量為10。
- LinkedList(): 在實現中採用連結串列資料結構。插入和刪除速度快,訪問速度慢。
對於List的隨機訪問來說,就是隻隨機來檢索位於特定位置的元素。 List 的 get(int index) 方法放回集合中由引數index指定的索引位置的物件,下標從“0” 開始。最基本的兩種檢索集合中的所有物件的方法:
1: for迴圈和get()方法:
2: 使用 迭代器(Iterator):
List主要分:
List:最大的特點是有序,它保證維護元素特定的順序。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(這隻推薦LinkedList使用。)一個List可以生成ListIterator,使用它可以從兩個方向遍歷List,也可以從List中間插入和移除元素。
ArrayList:由陣列實現。允許對元素進行快速隨機訪問,但是向List中間插入與移除元素的速度很慢。ListIterator只應該用來由後向前遍歷 ArrayList,而不是用來插入和移除元素。因為那比LinkedList開銷要大很多。
LinkedList :對順序訪問進行了優化,向List中間插入與刪除的佔用並不大。隨機訪問則相對較慢。(使用ArrayList代替。)還具有下列方法:addFirst(), addLast(),getFirst(),getLast(), removeFirst() 和 removeLast(), 這些方法 (沒有在任何介面或基類中定義過)使得LinkedList可以當作堆疊、佇列和雙向佇列使用。
介面的常用方法
add() 新增
remove() 移除
import java.util.ArrayList;
import java.util.Collection;
public class TestColle {
public static void main(String[] args) {
// TODO Auto-generated method stub
Collection c=new ArrayList();
c.add(1);
c.add("hello");
c.add(new Person());
System.out.println(c);
c.remove(1);
c.remove("hello");
c.remove(new Person());//用new新建立的equls時找不到原來的new 建立的所以移除不了
System.out.println(c.size());
System.out.println(c);
}
}
class Person{
@Override
public String toString() {
return "Person [hi]";
}
}
List介面其他常用方法
1 package until;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 public class Test1 {
7 public static void main(String[] args) {
8 List li=new ArrayList();
9 List lis=new ArrayList();
10
11 for(int i=0;i<5;i++){
12 li.add("string"+i);
13 if(i%2==0){
14 lis.add("string"+i);
15 }
16 }
17 System.out.println(li);
18 System.out.println(li.get(2));//獲取該索引位置的值
19 System.out.println(li.set(1, "Hello"));//將某個索引的值設定為另一個物件,然後將原來的索引的值返回
20 System.out.println(li);
21 System.out.println(li.remove(4));//刪除物件並將刪除的物件返回
22 System.out.println(li.indexOf("string0"));//返回該物件第一次出現的位置
23 System.out.println(li.lastIndexOf("string0"));//返回該物件最後一次出現的位置
24 System.out.println(li.retainAll(lis));//取二者的交集賦給第一個集合,如果兩個第一個集合改變了返回true
25 System.out.println(li);
26 }
27 }
Map(對映):
Map 是一種把鍵物件和值物件對映的集合,它的每一個元素都包含一對鍵物件和值物件。 Map沒有繼承於Collection介面 從Map集合中檢索元素時,只要給出鍵物件,就會返回對應的值物件。
Map的執行效率相對低下。
Map包含:
Map : 維護“鍵值對”的關聯性,使你可以通過“鍵”查詢“值”
HashMap:Map基於散列表的實現。插入和查詢“鍵值對”的開銷是固定的。可以通過構造器設定容量capacity和負載因子load factor,以調整容器的效能。
LinkedHashMap: 類似於HashMap,但是迭代遍歷它時,取得“鍵值對”的順序是其插入次序,或者是最近最少使用(LRU)的次序。只比HashMap慢一點。而在迭代訪問時發而更快,因為它使用連結串列維護內部次序。
TreeMap : 基於紅黑樹資料結構的實現。檢視“鍵”或“鍵值對”時,它們會被排序(次序由Comparabel或Comparator決定)。TreeMap的特點在 於,你得到的結果是經過排序的。TreeMap是唯一的帶有subMap()方法的Map,它可以返回一個子樹。
WeakHashMao :弱鍵(weak key)Map,Map中使用的物件也被允許釋放: 這是為解決特殊問題設計的。如果沒有map之外的引用指向某個“鍵”,則此“鍵”可以被垃圾收集器回收。
IdentifyHashMap: : 使用==代替equals()對“鍵”作比較的hash map。專為解決特殊問題而設計。
Map介面常用方法
package until;
import java.util.HashMap;
import java.util.Map;
public class Test1 {
public static void main(String[] args) {
Map map = new HashMap();
for (int i = 0; i < 5; i++) {
map.put(i, new Person("name" + i));//迴圈新增
}
System.out.println(map);
map.put(5, new Person("Xman"));//再次新增
System.out.println(map);
map.put(1, new Person("NewMan"));//在已有的鍵上新增替換
System.out.println(map);
System.out.println(map.get(5));//獲取指定的鍵的值
System.out.println(map.remove(0));//刪除鍵的值並返回值
System.out.println(map.remove(0, "na"));//刪除鍵值,成功返回true
System.out.println(map.containsKey(4));//判斷是否包含該鍵
System.out.println(map.containsValue(new Person("name0")));//判斷是否有該值
System.out.println(map.size());//返回有多少對
System.out.println(map.isEmpty());//返回是否空
map.clear();//清空
System.out.println(map);
Map map2=new HashMap();
map2.putAll(map);//新增另一個map集合
System.out.println(map2);
}
}
class Person{
String name;
public Person(String name) {
this.name = name;
}
@Override
public String toString() {
return "P ["+ name + "]";
}
}
Set介面
Set是最簡單的一種集合。集合中的物件不按特定的方式排序,並且沒有重複物件。 Set介面主要實現了兩個實現類:
HashSet: HashSet類按照雜湊演算法來存取集合中的物件,存取速度比較快
TreeSet :TreeSet類實現了SortedSet介面,能夠對集合中的物件進行排序。
Set具有與Collection完全一樣的介面,因此沒有任何額外的功能。(這是繼承與多型思想的典型應用:表現不同的行為。)Set不儲存重複的元素。 存入Set的每個元素都必須是唯一的,因為Set不儲存重複元素。加入Set的元素必須定義equals()方法以確保物件的唯一性。Set與Collection有完全一樣的介面。Set介面不保證維護元素的次序。
HashSet:為快速查詢設計的Set。存入HashSet的物件必須定義hashCode()。
TreeSet: 儲存次序的Set, 底層為樹結構。使用它可以從Set中提取有序的序列。
LinkedHashSet:具有HashSet的查詢速度,且內部使用連結串列維護元素的順序(插入的次序)。於是在使用迭代器遍歷Set時,結果會按元素插入的次序顯示。
三、總結與注意
Collection 和 Map 的區別
容器內每個為之所儲存的元素個數不同。
Collection型別者,每個位置只有一個元素。
Map型別者,鍵值對,類似於資料庫。
注意:
1.Collection、List、Set、Map都是介面,不能例項化。繼承自它們的 ArrayList, Vector, HashTable, HashMap是具象class,這些才可被例項化。
2. 如果涉及到堆疊,佇列等操作,應該考慮用List,對於需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
3. 在除需要排序時使用TreeSet,TreeMap外,都應使用HashSet,HashMap,因為他們 的效率更高。
4. 容器類僅能持有物件引用(指向物件的指標),而不是將物件資訊copy一份至數列某位置。一旦將物件置入容器內,便損失了該物件的型別資訊。
5. 儘量返回介面而非實際的型別,如返回List而非ArrayList,這樣如果以後需要將ArrayList換成LinkedList時,客戶端程式碼不用改變。這就是針對抽象程式設計。
6、Collection沒有get()方法來取得某個元素。只能通過iterator()遍歷元素。
7、List,可以通過get()方法來一次取出一個元素。使用數字來選擇一堆物件中的一個,get(0)...。(add/get)
8、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個key/value。HashMap會利用物件的hashCode來快速找到key。
9、Map中元素,可以將key序列、value序列單獨抽取出來。
使用keySet()抽取key序列,將map中的所有keys生成一個Set。
使用values()抽取value序列,將map中的所有values生成一個Collection。
因為,key總是獨一無二的,value允許重複。