java基礎---------集合之Collection與List



第一部分  Collection(集合)

在集合之前,我們就學過裝元素的容器數組。數組可以裝兩種類型,一種是基本數據類型,一種是引用數據類型。基本數據類型如byte,short,char,int,long,float,double,boolean。這也是我們比較常用的數組裝元素。數組裝引用類型,比如有一個Student類,我們就可以通過創建對象,將對象裝入數組。另一個我們常用但是卻容易忽視的引用數據類型就是String類型。比如String [] arrString={"我","愛","藍","色"};這也是一個數組裝引用數據類型的例子。
由於java是面向對象的語言,因此在實際開發中,常常就會直接操作對象。雖然數組可以裝引用類型,但是數組的長度固定,這就限制了數組在某些方面的應用。集合就是伴隨着將對象作爲元素而產生的容器。集合和數組的區別如下:
A:長度區別
數組固定
集合可變
B:內容區別
數組可以是基本類型,也可以是引用類型
集合只能是引用類型
C:元素內容
數組只能存儲同一種類型
集合可以存儲不同類型(其實集合一般存儲的也是同一種類型)
java集合大致可以分爲Set、List和Map三種體系,其中Set代表無序,不可重複的集合;List代表有序、重複的集合;而Map代表具有映射關係的集合。在java1.5之前,容器中對象的數據類型,都是當做Object類型處理,在Java1.5之後增加了泛型,使得java集合可以記住對象的數據類型,使得代碼更加簡潔健壯。

一些主要集合之間的關係如圖:
    Collection
|--List
|--ArrayList
|--Vector
|--LinkedList
|--Set
|--HashSet
|--TreeSet
Map
|HashMap
|LinkedHashMap
|TreeMap
Colletion與Map都是頂層接口。分別以他們爲接口的集合,都重寫了他們的方法,因此只要將這兩個接口中的方法弄明白,就可以大致將集合的特點掌握得八九不離十。

一、Collection<E>:
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():元素的個數 
 6:交集功能
  boolean retainAll(Collection c):兩個集合的交集
  7:把集合轉換爲數組
  Object[] toArray()


上面這些是Collection系列集合的常見功能。其中添加功能,獲取功能最爲重要。
import java.util.Collection;
import java.util.ArrayList;
class CollectionDemo{
	public static void main(String [] args){
		Collection c=new ArrayList();//這裏用的是其List的實現類ArrayList。這個集合的特點是有序,可重複。	
	}
}


由於Collection是一個接口,因此我們在使用Collection接口中的方法時,就需要創建一個接口對象,但接口對象是通過其實現類來實現的。因此我們就選擇了它的一個實現類ArrayList。


創建好對象後,我們就可以向該集合添加元素。我們可以添加String類型的:
c.add("好好學習");
c.add("天天向上");
c.add("是個好地方");

我們也可以添加Integer類型的。
c.add(1);
c.add(520);

這裏我們需要注意的是我們添加的並不是int類型的基本數據類型,而是Integer類型的,因爲其實現了自動裝箱,就相當於:
c.add(Integer.valueOf(1));
c.add(Integer.valueOf(520));		
     
但是如果我們在創建集合對象的時候就限定了泛型的話,如:
Collection<String> c=new ArrayList<String>();

那我們就只能爲集合c添加String類型的元素了。此時我們再添加Integer類型的話,就會編譯報錯。這就是泛型的優點,能將錯誤提前到編譯器。


(1)、集合遍歷迭代器
當我們在集合中定義了泛型爲String,並且添加了"好好學習""天天向上"  "是個好地方" 三個字符串後,我們遍歷集合就可以通過其獲取功能——迭代器Iterator<E>;當我們使用迭代器時,需要先導包。其方法主要有:
判斷:boolean hasNext():如果仍有元素可以迭代,則返回true
獲取:next() 返回迭代的下一個元素
移除 void remove() 從迭代器指向的 collection 中移除迭代器返回的最後一個元素(可選操作)
i
mport java.util.Iterator;
........
Iterator<String> it=c.iterator();
while(it.hasNext()){
	String s=it.next();
	System.out.println(s);
}

將會依次輸出:
好好學習 
天天向上
是個好地方

從結果我們也證明了前面所說的,ArrayList集合具有有序性,就是能夠按照元素添加的順序來依次輸出。上面的it.hasNext()起到了判斷集合中是否仍有元素的功能。


(2)集合轉數組遍歷
.......
Object [] obj=c.toArray();
for(int x=0;x<obj.length;x++){
	System.out.println(obj[x]);
}


輸出結果同上。但是需要我們注意的是上面通過迭代器輸出的是字符串類型,而下面通過數組遍歷的結果是Object類型。


練習題:

定義一個靜態方法,將List<Integer>傳入,即可排序。


<span style="font-size:14px;">/</span>/定義一個方法,將List集合作爲形式參數。
public static void Paixu(List<Integer> list){
	//定義一個數組,其長度爲list.size();
		int [] arr=new int[list.size()];
	//遍歷該數組的同時,將集合中的Integer類型的值通過自動拆箱後,賦給數組中對應的位置
		for(int x=0;x<list.size();x++){
			arr[x]=list.get(x);
			}
	//通過冒泡排序,將獲得了元素值的該數組進行排序
		for(int x=0;x<arr.length-1;x++){
			for(int y=0;y<arr.length-1-x;y++){
				if(arr[y]>arr[y+1]){
					int temp=arr[y];
					arr[y]=arr[y+1];
					arr[y+1]=temp;
				}
			}
		}
	//遍歷排序後的數組,將每個int類型元素,再通過自動裝箱添加進集合list。
		for(int x=0;x<arr.length;x++){
			System.out.println(arr[x]);
			list.add(Integer.valueOf(arr[x]));
		}
		
	}


第二部分list<E>;

有序(存儲和取出的元素一致),可重複

List接口繼承了Collection接口,因此Collection中的功能List都可以使用。這裏可以參考上面,比如在創建對象的時候,我們需要創建List的實現類對象。遍歷的時候可以通過Iterator迭代器遍歷,也可以通過for循環遍歷。
List集合的特有功能:
A:添加功能
 void add(int index,Object element):在指定位置添加元素
B:獲取功能
Object get(int index):獲取指定位置的元素
C:列表迭代器
ListIterator listIterator():List集合特有的迭代器
D:刪除功能
Object remove(int index):根據索引刪除元素,返回被刪除的元素
E:修改功能
Object set(int index,Object element):根據索引修改元素,返回被修飾的元素


import java.util.List;
import java.util.ArrayList;
class ListDemo{
	public static void main(String [] args){
		//創建一個List集合
		List<String> list=new ArrayList<String>();
		//添加String類型的元素
		list.add("hello");
		list.add("it");
		list.add("heima");
		list.add("heima");
		//通過List的特有方法,實現遍歷
		for(int x=0;x<list.size();x++){
			System.out.println(list.get(x));
		}			
		
	}	


}


輸出有序可重複的結果:
hello
it
heima
heima


ListIterator列表迭代器和Iterator迭代器遍歷的異同。

通過List特有的列表迭代器遍歷

import java.util.ListIterator;
.......
ListIterator<String> lit=list.listIterator();
	while(lit.hasNext()){
		String s=lit.next();
		System.out.println(s);
	}


通過Collection集合所共有的Iterator迭代器來實現。
import java.util.Iterator;
..........
Iterator<String> it=list.iterator();
while(it.hasNext()){
	String s=it.next();
	System.out.println(s);
}

粗略看ListIterator迭代器和Iterator迭代器沒什麼差別,但其實ListIterator有一個previous()方法可以獲取前一個元素。
import java.util.ListIterator;
.......
ListIterator<String> lit=list.listIterator();
	while(lit.hasPrevious()){
		String s=lit.previous();
		System.out.println(s);
	}

輸出逆序的結果:
heima
heima
it
hello
注意:這裏需要指出的是lit.hasPrevious()判斷前一個元素是否存在,如果開始就以第一個元素爲第一個元素,那麼就沒有前一個元素,因此這種方法就無法輸出。只有當正向遍歷之後,也就是lit.hasPrevious()判斷的不是以第一個元素爲標準的時候,纔是有意義的


練習題:

判斷一個集合中是否有字符串"it",如果有的話,就添加"heima";

import java.util.List;
import java.util.ArrayList;
import java.util.ListIterator;
class ExerciseDemo{
	public static void main(String [] args){
		//創建一個集合
		List<String> list=new ArrayList<String>();
		//爲集合添加元素
		list.add("wo");
		list.add("xi");
		list.add("huan");
		list.add("it");
		list.add("lesson");
		//創建列表迭代器
		ListIterator<String> ite=list.listIterator();
		//迭代器遍歷,迭代器添加
		while(ite.hasNext()){
			if(ite.next().equals("it")){
				//列表迭代器添加元素
				ite.add("heima");//這裏添加的"heima"將會在it字符之後。
			}
		}
		System.out.println(list);
		System.out.println("**************************");
		//for循環遍歷,集合添加
		for(int x=0;x<list.size();x++){
			if(list.get(x).equals("it")){
				list.add("heima");//這裏添加的"heima"將會在集合的最後。
			}
			System.out.println(list.get(x));
		}
		System.out.println(list);
	}
}


輸出結果爲:
[wo, xi, huan, it, heima, lesson]
**************************
[wo, xi, huan, it, heima, lesson, heima]


注意:通過輸出結果我們會發現:通過迭代器添加的"heima"位於"it"之後;
通過for循環添加的"heima",則位於集合的最後。







常見數據結構
A:棧 先進後出
B:隊列 先進先出
C:數組 查詢快,增刪慢
D:鏈表 查詢慢,增刪快




List的子類特點
ArrayList:
底層數據結構是數組,查詢快,增刪慢。
線程不安全,效率高。
Vector:
底層數據結構是數組,查詢快,增刪慢。
線程安全,效率低。
LinkedList:
底層數據結構是鏈表,查詢慢,增刪快。
線程不安全,效率高。


第三部分ArrayList
底層數據結構是數組,查詢快,增刪慢。線程不安全,效率高。有序可重複


練習題:
去除集合中字符串的重複值

import java.util.ArrayList;
import java.util.Iterator;
class ArrayListDemo{
	public static void main(String [] args){
		//創建一個集合
		ArrayList<String> array=new ArrayList<String>();
		//爲集合添加元素
		array.add("wo");
		array.add("xi");
		array.add("huan");
		array.add("xi");
		array.add("huan");
		array.add("huan");
		array.add("it");
		array.add("heima");	
		//創建一個新集合
		ArrayList<String> newArray=new ArrayList<String>();
		//迭代器遍歷舊集合
		Iterator<String> it=array.iterator();	
		while(it.hasNext()){
			String s=it.next();
			//如果新集合中包含集合中某元素,就不添加,否則就添加
			if(!newArray.contains(s)){
				newArray.add(s);
			}
		}
		//遍歷新集合
		for(String s:newArray){
			System.out.println(s);
		}
	}
}


輸出結果爲:
wo
xi
huan
it
heima




第二種方法:
import java.util.ArrayList;
import java.util.Iterator;
class ArrayListDemo{
	public static void main(String [] args){
		//創建一個集合
		ArrayList<String> array=new ArrayList<String>();
		//爲集合添加元素
		array.add("wo");
		array.add("xi");
		array.add("huan");
		array.add("xi");
		array.add("huan");
		array.add("huan");
		array.add("it");
		array.add("heima");	
		for(int x=0;x<array.size()-1;x++){
			for(int y=x+1;y<array.size();y++){
				if(array.get(x).equals(arr.get(y))){
					array.remove(y);
					y--;//如果不進行y--的話,第二個huan被第一個huan移除的時候,第三個huan就上前一個位置,從而不再被比較。
				}
			}
		}
		for(String s:array){
			System.out.println(s);
		}		
	}
}




去除集合中自定義類的重複值(成員變量值相同)
import java.util.ArrayList;
import java.util.Iterator;
class ArrayListDemo{
	public static void main(String [] args){
		//創建一個集合
		ArrayList<School> array=new ArrayList<School>();
			//創建School對象
		School s1=new School("藍色",100);
		School s2=new School("清華",90);
		School s3=new School("北大",90);
		School s4=new School("武大",80);
		School s5=new School("浙大",80);
		School s6=new School("清華",90);
		School s7=new School("武大",80);
		//將對象添加到集合
		array.add(s1);
		array.add(s2);
		array.add(s3);
		array.add(s4);
		array.add(s5);
		array.add(s6);
		array.add(s7);
		//創建新集合
		ArrayList<School> newArray = new ArrayList<School>();
		//通過迭代器遍歷舊集合
		Iterator<School> it=array.iterator();
		while(it.hasNext()){
			School s=it.next();
			//如果新集合中存在與對象的成員變量相同的對象,就不添加,否則就添加。
			if(!newArray.contains(s)){
				newArray.add(s);
			}
		}
			//遍歷新集合
		for(School s:newArray){
			System.out.println(s.getName()+"******"+s.getAge());
		}		
	}
}
//創建自定義類
class School{
		//私有成員變量
	private String name;
	private int age;
	//帶參構造函數
	public School(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	//重寫equals()
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		School other = (School) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	//無參構造方法
	public School() {
		super();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}


輸出結果爲:
藍色******100
清華******90
北大******90
武大******80
浙大******80


注意:contains()的底層依賴的equals().因此這裏需要在自定義類中重寫equals().  

ArrayList集合的排序在Map集合這一篇博客中的最後也有介紹,有兩種,一種是自然排序,實現comparable接口。一種是比較器排序。ArrayList實現了排序與去重複功能後就會變得特別強大。



第四部分Vector


底層數據結構是數組,查詢快,增刪慢。線程安全,效率低。有序可重複
Vector出現比較早,在JDK1.0的時候就出現了,但是集合是在JDK1.2才加進來的。因此Vector會有一些特殊方法。
a:添加
public void addElement(E obj)--add()
b:獲取
public E elementAt(int index)--get()
public Enumeration<E> elements()--  iterator()
boolean hasMoreElements()--hasNext()
Object nextElement()--next()


Vector集合中的addElement()被Collection中的add()取代。elementAt()被get()取代。element()被iterator()取代。




第五部分LinkedList 有序可重複


底層數據結構是鏈表,查詢慢,增刪快。線程不安全,效率高。
LinkedList的特有功能:
A:添加功能
public void addFirst(Object e) //添加在集合的最前。如果一直用addFrist()來添加元素的話,就可以先添加的最後取出。
 public void addLast(Object e)
B:獲取功能
public Object getFirst()
public Obejct getLast()
C:刪除功能
 public Object removeFirst()
 public Object removeLast()


練習題:

用LinkedList模擬棧數據結構的結合。

import java.util.LinkedList;
public class MyStackDemo {
	public static void main(String[] args) {
		// 創建集合對象
		MyStack ms = new MyStack();
		// 添加元素
		ms.add("hello");
		ms.add("world");
		ms.add("java");
		//遍歷該集合,如果爲空,就停止。
		while(!ms.isEmpty()){
			System.out.println(ms.get());
		}
	}
}
class MyStack {
	//定義一個變量link,其類型爲LinkedList;
	private LinkedList link;
	//無參構造。如果調用該構造,將會創建一個LinkedList(),並將其賦給變量link
	public MyStack() {
		link = new LinkedList();
	}
	public void add(Object obj) {
	//link爲LinkedList類型,所以可以調用該方法
		link.addFirst(obj);
	}
	public Object get() {
		return link.removeFirst();
	}
	public boolean isEmpty() {
	//判斷該集合是否爲空
		return link.isEmpty();
	}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章