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(): 在實現中采用鏈表數據結構。插入和刪除速度快,訪問速度慢。
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允許重復。Java之集合初探(一)