1. 程式人生 > >黑馬程式設計師--Java基礎--集合(一)

黑馬程式設計師--Java基礎--集合(一)

------- android培訓java培訓、期待與您交流! ----------

第一部分:集合框架概述

集合的由來:物件用於封裝特有資料,物件多了需要儲存;如果物件的個數不確定,就使用集合容器進行儲存。

Java中有兩種儲存物件:陣列和集合。

它們的區別在於:

1、陣列的長度一旦定義了就是固定的,而集合長度是可變的。

2、陣列中可以儲存基本資料型別,集合只能儲存物件。

因此從這裡可以得出集合的特點::

a. 用於儲存物件的容器。

b. 集合的長度是可變的。

c. 集合中不可以儲存基本資料型別值。

根據資料儲存的方式(即資料結構)的不同,可以分為不同的集合容器。這些不同的集合容器不斷的向上抽取,就形成了頂層的集合框架就是Collection

下面代表了集合框架中List集合和Set集合的結構:

Collection

|--List:元素是有序的,元素可以重複。因為該集合體繫有索引。

|--|--ArrayList:底層的資料結構使用的是陣列結構。特點:查詢速度很快,但是增刪稍慢。執行緒不同步初始容量是10,超過以後按照百分之50進行延長。

|--|--LinkedList:底層的資料結構是連結串列結構。特點:增刪速度很快,查詢速度慢。

|--|--Vector:底層是陣列結構。執行緒同步。被ArrayList替代了。超過初始容量後按照百分之百延長。

|--Set:元素是無序的(存入和取出的順序不一定一致),元素不可以重複。

|--|--HashSet:底層資料結構是雜湊表。

|--|--TreeSet:可以對Set集合中的元素進行排序。

第二部分:迭代器物件Iterator

迭代器的概念:集合的取出元素的方式。

集合框架中將取出方式定義在集合的內部,作為集合的內部類,這樣就能直接訪問不同集合裡的內部元素。

為什麼要定義在內部?

因為每一個具體的集合容器的資料結構不同,所以取出的動作細節也不一樣。因此迭代器物件在具體容器中進行具體實現,不同容器的實現方式是不一樣的。但是都有共性的內容:判斷和取出。因此抽取出了共性,即迭代器物件Iterator

因此,通過對外提供的方法:Iterator()可以獲取集合的取出物件。

使用迭代器獲取元素的第一種方法程式碼示例:

//建立一個集合容器,使用Collection介面的子類,ArrayList
ArrayList a1 = new ArrayList();
a1.add("java01");//add(Object obj)
a1.add("java02");
a1.add("java03");
a1.add("java04");

Iterator it = a1.iterator();//這個方法返回的是Iterator的子類物件
while(it.hasNext())
{
        System.out.println(it.next());//獲取迭代器,用於取出集合中的元素
}

使用迭代器獲取元素的第二種方法程式碼示例:
for(Iterator it1 = a1.iterator();it1.hasNext();)
{
	System.out.println(it1.next());
}

第三部分:集合框架的共性方法

集合的頂層是Collection介面,這個介面中定義了常見的共性方法:

1、新增:

boolean add(Object obj);

boolean addAll(Collection coll);

add()方法程式碼示例:

//建立一個集合容器,使用Collection介面的子類,ArrayList
ArrayList a1 = new ArrayList();
a1.add("java01");
a1.add("java02");
a1.add("java04");

2、刪除:

boolean remove(Object obj);

boolean removeAll(Collection coll);

remove()方法程式碼示例:

a1.remove("java02");

void clear();

clear()方法示例:

a1.clear();

3、判斷:

boolean contains(Object obj);判斷是否包含物件obj

contain()方法示例:

a1.contains("java03");

boolean containsAll(Collection coll);

boolean isEmpty();判斷集合中是否有元素。

 isEmpty()方法示例

 a1.isEmpty();

4、獲取

int size();

size()方法示例:

a1.size();
Iterator iterator();

5、其他

boolean retainAll(Collection coll);取兩個集合的交集

retainAll()方法示例:

<span style="white-space:pre">		</span>ArrayList a1 = new ArrayList();
		a1.add("java01");
		a1.add("java03");
		
		ArrayList a2 = new ArrayList();
		a2.add("java01");
		a2.add("java04");

		a1.retainAll(a2);//取交集,a1中只會保留和a2中相同的元素
		System.out.println(a1);
		System.out.println(a2);
輸出結果是:
[java01]
[java01, java04]

boolean removeAll(Collection coll);去掉兩個集合的交集

removeAll()方法例項:

		a1.removeAll(a2);//a1中把和a2相同的元素去掉
                System.out.println(a1);
                System.out.println(a2);

輸出結果是:
[java03]
[java01, java04]

第四部分:List集合

1、在List集合容器中,擁有特殊的共性方法:凡是可以操作角標的方法都是該體系中特有的方法。

a、新增:

void add(int index,E element);

ArrayList al = new ArrayList();
al.add("java01");
al.add("java02");
al.add("java03");

//在第二位新增元素
al.add(1,"java09");
boolean addAll(int index,Collection coll);
b、刪除

boolean remove(int index);

al.remove(2);

c、修改

E set(int index,E element);

al.set(2,"java007");

d、查詢

E get(index);

//獲取所有元素,List的特有方式
for(int x = 0;x<al.size();x++)
{
        al.get(x);
}
List<E> subList(int from,int to);
List sub = al.subList(1,2);
ListIterator<E> listIterator();

注:ListIterator是List集合特有的迭代器,它是Iterator的子介面。

在迭代時,只能用用迭代器Iterator的方法操作元素,可是迭代器Iterator的方法是有限的,只能對元素進行判斷、取出和刪除操作。如果想要進行新增、修改,則會發生併發修改異常。

因此,在List集合中想要對元素在迭代過程中進行新增、修改,則必須用ListIterator迭代器。

程式碼示例:

		/*
		//在迭代過程中,準備新增或者刪除元素
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();
			if(obj.equals("java02")
				//al.add("java008");//修改異常,不能用集合同時用迭代器操作元素。這個是併發修改
				it.remove();//把java02的引用從集合中刪除了
		}
		*/

		ListIterator li = al.listIterator();
		while(it.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("java02"))
				li.add("java009");//在java02後面添加了java009
				//li.set("java006");把java02修改成java006
		}
同時在ListIterator物件中提供了逆向遍歷方法:hasPrevious()和previous()。程式碼示例:
                ListIterator li = al.listIterator();
		while(li.hasPrevious())
		{
			sop(li.previous());//逆向取元素
		}

2、LinkedList集合容器的特有方法:

a、新增

addFirst(Object obj);

addLast(Object obj);

jdk1.6版本後新方法:

offerFirst();與addFirst方法沒有區別。

offerLast();與addLast方法沒有區別。

b、獲取

getFirst();

getLast();

特點:獲取元素,但不刪除元素。如果集合中沒有元素,會出現NoSuchElementException

jdk1.6版本後新方法:

peekFirst();

peekLast();

特點:獲取但不移除,如果連結串列為空,返回null。

c、刪除

removeFirst();

removeLast();

特點:獲取元素,但是元素被刪除。如果集合中沒有元素,會出現NoSuchElementException

pollFirst();

pollLast();

特點:獲取並移除,如果連結串列為空,返回null;

3、List集合判斷元素是否相同(例如contain方法和remove方法),依據的是元素的equals()方法。

例如:以Person類為物件存入ArrayList中,同性名同年齡的視為同一個人,不能加為同一個人。

這時候要在Person類中新增一個equals方法,對姓名name和年齡age進行判斷

程式碼示例:

import java.util.ArrayList;
import java.util.Iterator;

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	//覆寫equals方法。
	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age==p.age;
	}
}

class  HelloDemo
{
	//定義一個新方法,對ArrayList容器裡的元素按照name和age進行比較,然後返回一個新的不帶重複元素的ArrayList
	public static ArrayList singleElement(ArrayList al)
	{
		//定義一個臨時容器
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();
			if(!newAl.contains(obj))
				newAl.add(obj);
		}
		return newAl;	
	}	
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		//a1.add(Object obj)-->Object obj = new Person(..)-->型別自動提升
		al.add(new Person("lisi01",30));
		al.add(new Person("lisi02",43));
		al.add(new Person("lisi02",43));
		al.add(new Person("lisi03",23));
		al.add(new Person("lisi04",32));
		al.add(new Person("lisi04",32));

		ArrayList newAl = singleElement(al);
		
		Iterator it = newAl.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();
			System.out.println(p.getName()+"::"+p.getAge());
		}
	}
}

4、Vector容器的列舉。

列舉是Vector的特有方式,但是作用和迭代器一致。

因為列舉的名稱以及方法的名稱都過長,所以被迭代器取代了

程式碼示例:

		Vector v = new Vector();
		v.add("java01");
		v.add("java02");
		v.add("java03");
		v.add("java04");
		
		Enumeration en = v.elements();
		while(en.hasMoreElements())
		{
			System.out.println(en.nextElement());
		}

第五部分:Set集合

1、set集合的元素的特點:

a、元素是無序的(存入和取出的順序不一定一致);

b、元素不可以重複

Set介面中的方法和Collection一致。

2、HashSet

HashSet的底層資料結構是雜湊表。

重點:HashSet容器保證元素唯一性的方法:

通過元素的兩個方法,hashCode()和equals()來完成的。

首先,如果元素的hashCode()方法返回的雜湊值是否相等;

其次,如果hashCode()方法返回的雜湊值不相等,才會呼叫equals()方法判斷內容是否相同。

因此,雜湊表確定元素是否相同的步驟是:先判定雜湊值,如果不同再判斷兩物件內容是否相同。

例子:使用HashSet儲存自定義物件,這裡要儲存的是Person類物件,如果姓名和年齡相同視為同一個人

import java.util.*;
class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	//一般要覆寫hashCode()和equals()方法
	public int hashCode()
	{
		return name.hashCod()+age*39;//一般要乘以一個數保證雜湊值的唯一性
	}
	public boolean equals(Object obj)
	{
		if(!obj instanceof Person)
			throw new RuntimeException("不是學生物件");
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age==p.age;
	}
	public int getAge()
	{
		return age;
	}
}
class  
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();
		hs.add(new Person("java01",11);
		hs.add(new Person("java02",12);
		hs.add(new Person("java03",13);
		hs.add(new Person("java02",12);
		

		Iterator it = hs.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();
			sop(p.getName()+p.getAge());
		}

	}
}
3、TreeSet

TreeSet的底層是排序二叉樹,左子樹比右子樹大。取出時候按照中序遍歷取出元素。

TreeSet保證元素唯一性的方式:就是compareTo()方法是否返回0,如果返回0則判斷這兩個元素相等。

重點:TreeSet排序的兩種方式:

a、如果元素本身具備比較性,使用元素實現Comparable介面,然後覆寫compareTo()方法。這種方式是利用了元素的自然順序。

b、當元素自身不具備比較性時,或者具備的比較性不是所需要的,這時就需要讓集合自身具備比較性。具體方法是定義一個類實現Comparator介面,覆蓋compare方法。將該類物件作為引數傳遞給TreeSet集合的建構函式。

P.S. 當兩種方式都存在時,以第二種方式、即以比較器為主

假設儲存Student類物件,按照年齡age和姓名name排序

下面是第一種方式的程式碼示例:

class Student implements Comparable//該介面強制讓學生具備比較性
{
	private String name;
	private int age;

	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	//覆寫方法,這個方法可以對物件進行比較排序。該方法先按照年齡進行排序,然後再按照姓名排序。
	public int compareTo(Object obj)
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是學生物件");
		Student s = (Student)obj;
		if(this.age > s.age)
			return 1;
		if(this.age == s.age)
		{
			return this.name.compareTo(s.name);//很多類都具有compareTo方法
		}
		return -1;
		
	}
}
<pre name="code" class="java">//主函式
class  Demo
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();
		ts.add(new Student("aisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("bisi09",22));
		ts.add(new Student("lisi01",40));
		
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();//這裡一定要強制轉換回原有。
			System.out.println(stu.getName()+":"+stu.getAge());
		}
	}
}
接下來是第二種方式:
//實現MyCompare類來實現比較器介面,然後覆寫比較器Comparator接口裡的方法compare()方法。
//這個比較器和上面相反,先按照姓名name排序後再按照年齡age排序
class MyCompare implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;
		int num = s1.getName().compareTo(s2.getName());
		if(num == 0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		return num;
	}
}
//主函式
<pre name="code" class="java">class  HelloDemo
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new MyCompare());//在TreeSet建構函式中就要作為引數傳入。
		ts.add(new Student("aisi02",22));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("bisi09",22));
		ts.add(new Student("lisi01",40));
		
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+":"+stu.getAge());
		}
	}
}


P.S.:有一個需求是TreeSet怎麼存入元素就怎麼取出來的辦法是:co'mpareTo方法直接return 1即可。


相關推薦

黑馬程式設計師--Java基礎--集合

------- android培訓、java培訓、期待與您交流! ---------- 第一部分:集合框架概述 集合的由來:物件用於封裝特有資料,物件多了需要儲存;如果物件的個數不確定,就使用集合容器進行儲存。 Java中有兩種儲存物件:陣列和集合。 它們的區別在於:

黑馬程式設計師——Java基礎--集合

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 第一講 集合的基本知識 一、概述         我們學習的是面向物件的語言,而面向物件的語言對事物的表述都是通過物件體現的。那麼為了方便的操作多個多個

黑馬程式設計師——Java面向物件之匿名物件、程式碼塊、static關鍵字等

   a)子類只繼承父類的預設(預設)建構函式,即無形參建構函式。如果父類沒有預設建構函式,那子類不能從父類繼承預設建構函式。    b)子類從父類處繼承來的父類預設建構函式,不能成為子類的預設建構函式。    c)在建立物件時,先呼叫父類預設建構函式對物件進行初始化,然後呼叫子類自身自己定義的建構函

黑馬程式設計師——Java IO流之IO流概述、字元流、位元組流等

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ IO流 一、概述 1.IO流是用來處理裝置之間的資料傳輸。  2.Java對資料的操作時通過流的方式。  3.Java用於操作流的物件都在IO包中。  

黑馬程式設計師-----Java基礎-----集合框架詳解

------<a href="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! ------- 經常會看到程式中使用了記錄集,常用的有

黑馬程式設計師----java基礎-------集合框架

      List 集合特有的迭代器,List Iterator是Iterator的子介面。       在迭代時,不可以通過集合物件的方法操作集合中的元素。       因為會發生ConcurrentModificationException異常。       class linkedlist Demo

黑馬程式設計師----JAVA基礎集合框架_迭代器

------ android培訓、java培訓、期待與您交流! ----------  個人認為總的來說,map不是地圖是對映的意思,所以裡面是鍵值成對存在的,list的清單的意思,所以裡面是一項一項列出來的,set是集合的意思,所以裡面不能有重複的(數學裡面的集合

黑馬程式設計師——Java基礎->集合框架

——Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ——- 為什麼出現集合類? • 面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多 個物件的操作,就對物件進行儲存,集合就是儲存物件最常用的一 種方式。 陣列和集合

黑馬程式設計師——java基礎——集合

------- android培訓、java培訓、期待與您交流! ---------- 面嚮物件語言對事物的體現都是以物件的形式,所以為了方便對多個物件的操作,Java就提供了集合類。 集合的繼承

黑馬程式設計師——Java IO流之流操作規律總結、File類、Properties類、序列流等

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 六、流操作規律總結  1.明確源和目的:   源:    字元流:FileReader(純文字檔案)。    位元組流:FileInputStream(

黑馬程式設計師——Java面向物件之封裝、繼承、多型、介面等

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 五、面向物件的特徵  面向物件主要有三大特徵: 1.特徵一 —— 封裝  1)定義:是指隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。 2)好處:

黑馬程式設計師——Java面向物件之內部類、異常、包等

-----------android培訓、java培訓、java學習型技術部落格、期待與您交流!------------ 六、物件的其他重要內容 1.單例設計模式  1)什麼是單例設計模式?   單例設計模式是指能夠確保一個類只有一個例項,並且能夠自行向整個系統提供這個例項

Java基礎——集合——集合體系、Collection集合

一、集合概述          Java是一種面嚮物件語言,如果我們要針對多個物件進行操作,就必須對多個物件進行儲存。而陣列長度固定,不能滿足變化的要求。所以,java提供了集合。          特點                 1.        長度可以發生改變

黑馬程式設計師_基礎加強註解

---------------------- ASP.Net+Android+IO開發S、.Net培訓、期待與您交流! ---------------------- 註解(annotation)是jdk1.5的新特性 瞭解註解及java提供的幾個基本註解 1)  先通過@S

黑馬程式設計師----Java基礎集合類()

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師——java基礎之string及集合

<span style="font-family:SimSun;font-size:18px;">class TreeSetDemo { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.

黑馬程式設計師——Java基礎---IO流字元流、位元組流、轉換流、流操作規律

三、字元編碼 字元編碼通過轉換流來完成。在兩個物件進行構造的時候,可以加入字符集(即編碼表),可傳入編碼表的有: 轉換流:InuputStreamReader和OutputStreamWriter。列印流:PrintStream和PrintWriter,只有輸出流。轉換流的編碼應用 可以將字元以指定編

黑馬程式設計師——java基礎拾遺之多執行緒 執行緒同步、執行緒通訊

執行緒安全的概念:當多個執行緒同時執行一段程式碼時,如果結果和單執行緒執行時一致,而且其他變數也和預期的一致,說明是這段程式碼是執行緒安全的。但是,多執行緒執行的過程中會出現單執行緒時候不會出現的問題,大多出現在多個執行緒同時操作全域性變數或者靜態變數的時候。當出現這種

黑馬程式設計師----Java基礎之反射

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g

黑馬程式設計師----Java基礎之GUI

------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a&g