由於每個容器對於數據的存儲方式都有不一樣,這個存儲方式稱之爲:數據結構
Collection有兩個常見的接口
List和Set
List分爲ArrayList LinkedList Vector
Set分爲HashSet和TreeSetjava
List中的元素是有序的,能夠重複,由於該集合體繫有索引
ArrayList:底層的數據結構使用的是數組結構,查詢速度快,增刪速度慢。
LinkedList:底層的數據結構使用的是鏈表結構,增刪速度快,查詢速度慢。
Vector:底層的數據結構使用的是數組結構,Vector和ArrayList比較類似,但Vector是線程同步的,ArrayList是不一樣步的。Vector是可變長度數組,ArrayList默認狀況下長度爲10,超過10時會新建一個長度15的數組,將舊數組copy到新數組中。Vector默認長度也爲10,超過10時自身會延長到20。相對而言Vector相對浪費空間。因爲Vector速度比較慢,被ArrayList替換了。web
1,add方法的參數類型是Object,以便於接收任意類型對象數組
2.集合中存儲的都是對象的引用(地址)數據結構
這是輸出函數sop()svg
public static void sop(Object obj) { System.out.println(obj); }
幾個簡單操做函數
ArrayList a1=new ArrayList(); //1,添加元素 a1.add("java1"); a1.add("java2"); a1.add("java3"); a1.add("java4"); ArrayList a2=new ArrayList(); a2.add("java1"); a2.add("java3"); a2.add("java5"); a2.add("java7"); //2,打印集合 sop(a1);//會直接封裝成列表 //3,刪除元素 //a1.remove("java2"); //打印刪除後的集合 //sop(a1); //清空集合 // a1.clear(); //4,判斷元素 sop("java3是否存在 "+a1.contains("java3")); //5,獲取個數。集合長度 sop("size="+a1.size()); //6,取交集 a1.retainAll(a2);//取交集而且保存在a1中 sop("a1 "+a1); sop("a2 "+a2);
迭代器:
迭代器是集合取出元素的方式this
public static void method_get()//取出元素,用sop直接輸出只能打印,不能取出進行其餘操做 { ArrayList a1=new ArrayList(); a1.add("java1"); a1.add("java2"); a1.add("java3"); a1.add("java4"); Iterator it=a1.iterator();//返回一個接口的子對象,獲取迭代器,用於取出集合中的元素 //sop(it.next());//取出一個元素 //sop(it.next());//再取出一個元素 //對於取出的動做,不足以用一個方法描述,須要多個方法配合。 //把取出動做封裝成對象放在集合內部。 while (it.hasNext())循環輸出對象 { sop(it.next()); } }
//for循環對內存的使用優於while循環,用完會自動釋放 for (Iterator it=a1.iterator();it.hasNext();) { sop(it.next()); }
把取出方式定義在集合的內部,這樣取出方式就能夠直接訪問集合內容的元素。那麼取出方式就被定義成了內部類。而每個容器的數據結構不一樣,因此取出的動做細節也不同。可是都有共性內容:判斷和取出。那麼能夠將這些共性抽取。那麼這些內部類都符合一個規則。該規則是Iterator。
ArrayList 特有方法。凡是能夠操做角標的方法都是該體系特有的方法。
增
add(index, element) ;
addAll (index, Collection) ;
刪
remove (index) ;
改
set (index, element) ;
查
get (index) ;
subList (from, to) ;
ListIterator () ;spa
//增長 // a1.add(1,"java09"); //sop("新集合 "+a1); //刪除 // a1.remove(2); //sop("新集合 "+a1); //修改 //a1.set(2,"java05"); //sop("新集合 "+a1); //查找 經過角標獲取元素 //a1.get(2); //sop("新集合 "+a1); //獲取全部元素 for (int i=0;i<a1.size();i++) { sop("ArrayList["+i+"]= "+a1.get(i)); }
List集合特有的迭代器。ListIterator是Iterator的子接口。
在迭代時,不可約經過集合對象的方法操做集合中的對象。
由於會發生ConcurrentModi ficationException異常。
因此,在迭代器時,只能用迭代器的放過操做元素,但是Iterator方法是有限的,只能對元素進行判斷,取出,刪除的操做,若是想要其餘的操做如添加,修改等,就須要使用其子接口,ListIterator。該接口只能經過List集合的listIterator方法獲取。
對於集合可使用這樣的操做:線程
Iterator it=a1.iterator(); ListIterator li=a1.listIterator(); while (li.hasNext()) { Object obj=li.next(); if (obj.equals("java2")) { li.set("java6");//循環到java2時將其修改成java6 } }
鏈表LinkedList:特有方法:
addFirst() ;
addLast() ;
getFirst () ;
getLast () ;
獲取元素,但不刪除元素。若是集合中沒有元素,會出現NoSuchElementException
removeFirst() ;
removeLast () ;
獲取元素,可是元素被刪除。若是集合中沒有元素,會出現NoSuchEl ementException
在JDK1.6出現了替代方法。
offerFirst() ;
offerLast () ;
:I
peekFitst () ;
peekLast () ;
獲取元素,但不刪除元素。若是集合中沒有元素,會返回null。
pollFirst() ;
pollLast () ;
獲取元素,可是元素被刪除。若是集合中沒有元素,會返回null。code
幾個LinkerList的小練習:
1 使用LinkedList模擬一個堆棧或者隊列數據結構。
這兩個是數據結構裏面的經典概念,並不陌生。
堆棧:先進後出如同一個杯子。
隊列:先進先出如同一個水管。
public class Main { public static void main(String[] args) { // write your code here Queue q=new Queue(); q.myadd("java01"); q.myadd("java02"); q.myadd("java03"); q.myadd("java04"); while (!q.isNull()) System.out.println(q.myget()); Stack s=new Stack(); s.myadd("java05"); s.myadd("java06"); s.myadd("java07"); s.myadd("java08"); while (!s.isNull()) System.out.println(s.myget()); } } class Queue//數據結構隊列 { private LinkedList link; Queue() { link=new LinkedList(); } public void myadd(Object object) { link.addFirst(object); } public Object myget() { return link.removeLast();//出隊 } public boolean isNull()//是否爲空 { return link.isEmpty(); } } class Stack //數據結構堆棧 { private LinkedList link; Stack() { link=new LinkedList(); } public void myadd(Object object) { link.addFirst(object); } public Object myget() { return link.removeFirst();//出隊 } public boolean isNull()//是否爲空 { return link.isEmpty(); } }
2 去除ArrayList中的重複元素
能夠經過新建ArrayList,遍歷,查重添加來實現。
public class Main { public static void main(String[] args) { // write your code here ArrayList a1=new ArrayList(); a1.add("java01"); a1.add("java02"); a1.add("java01"); a1.add("java02"); a1.add("java01"); sop(a1); a1=singelElement(a1); sop(a1); } public static ArrayList singelElement(ArrayList a1)//定義一個新的空容器,直接加入 { ArrayList newAl=new ArrayList(); Iterator it=a1.iterator();//迭代器 while (it.hasNext())//遍歷取出 { Object obj=it.next();//取下一個 if (!newAl.contains(obj)) newAl.add(obj); } return newAl; } public static void sop(Object object) { System.out.println(object); } }
另外
Iterator it=a1.iterator();//迭代器 while (it.hasNext()) { sop(it.next()+"...."+it.next()); }
對於這個循環,當ArrayList中含有奇數個元素時就會出現error。因此在迭代時循環中next()調用一次就要hasNext判斷一次。
3 將自定義對象做爲元素存到ArrayList集合中,並去除重複元素。
好比:存人對象。同姓名同年齡,視爲同一我的。爲重複元素。
public class Main { public static void main(String[] args) { // write your code here ArrayList a1=new ArrayList(); a1.add(new Person("Reveck",17));//a1.add(Object obj)=new Person("````") a1.add(new Person("Alice",18)); a1.add(new Person("Orianna",19)); a1.add(new Person("De Jong",21)); a1.add(new Person("Frenkie",22)); a1.add(new Person("Frenkie",22)); Iterator it=a1.iterator();//迭代器 while (it.hasNext()) { //sop(it.next().getNmae());//直接next返回的是Object對象,Object對象中沒有getNmae()方法,編譯不經過 Person p=(Person)it.next();//作強轉直接把it.next()給p sop(p.getName()+":"+p.getAge());//編譯成功 } a1=singelElement(a1); it=a1.iterator(); while (it.hasNext()) { //sop(it.next().getNmae()); Person p=(Person)it.next(); sop(p.getName()+":"+p.getAge());// } } public static ArrayList singelElement(ArrayList a1)//定義一個新的空容器,直接加入 { ArrayList newAl=new ArrayList(); Iterator it=a1.iterator();//迭代器 while (it.hasNext())//遍歷取出 { Object obj=it.next();//取下一個 if (!newAl.contains(obj)) newAl.add(obj); } return newAl; } public static void sop(Object object) { System.out.println(object); } } class Person { private String name; private int age; Person(String name,int age) { this.age=age; this.name=name; } public String getName() { return name; } public int getAge() { return age; } public boolean equals(Object obj) { if (!(obj instanceof Person)) return false; Person p=(Person)obj; //System.out.println(this.name+"....."+p.name);//觀察equal的過程是this和p在逐個比較 return this.name.equals(p.name)&&this.age==p.age; } }
這題的關鍵在於Person是一個自定義的類,要比較Person須要比較name和age,這須要經過向下轉型,重寫Object中的equals()來實現。因爲contains()函數中會調用equals,重寫equals以後就成了和上題差很少的狀況。作題過程當中經過在equals()中設置輸出來觀察比較的過程,也能成功理解原理。