1. 程式人生 > >黑馬程式設計師java之集合框架Collection

黑馬程式設計師java之集合框架Collection



------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a>、期待與您交流! ----------

Collection

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

List集合判斷元素是否相同,依據是元素的equals方法。

|--ArrayList:底層的資料結構使用的是陣列結構。特點:查詢速度很快。但是增刪稍慢。執行緒不同步。

|--LinkedList:

底層使用的連結串列資料結構。特點:增刪速度很快,查詢稍慢。執行緒不同步。

|--Vector:底層是陣列資料結構。執行緒同步。被ArrayList替代了。因為效率低。

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

|--HashSet:底層資料結構是雜湊表。是執行緒不安全的。不同步。

HashSet保證元素唯一性是通過元素的兩個方法,hashCodeequals來完成。如果元素的HashCode值相同,才會判斷equals是否為true。如果元素的hashcode值不同,不會呼叫equals

注意,對於判斷元素是否存在,以及刪除等操作,依賴的方法是元素的hashcode

equals方法。

|--TreeSet可以對Set集合中的元素進行排序。底層資料結構是二叉樹。

Collection定義了集合框架的共性功能。

1,新增add(e);新增e進入集合

2,刪除remove(e);removeAll();刪除全部元素

3,判斷。contains(e);判斷e是否存在。

isEmpty();判斷集合是否為空。

4,獲取

iterator();通過迭代獲取集合全部元素

size();獲取集合元素個數

5,獲取交集。retainAll();

6,集合變陣列。toArray();

集合的取出元素的方式。是用迭代器 Iterator

Iterator it = al.iterator();

獲取迭代器,用於取出集合中的元素。

while(it.hasNext()){//判斷集合是否有元素

sop(it.next());//列印元素

}

for(Iterator it = al.iterator(); it.hasNext() ; ){

sop(it.next());

}開發建議用這種,節省記憶體。

List特有方法。凡是可以操作角標的方法都是該體系特有的方法。

add(index,element);在指定位置新增元素。

addAll(index,Collection);

remove(index);

set(index,element);

get(index):獲取指定角標元素subList(from,to);

int indexOf(obj):獲取指定元素的位置。

ListIterator listIterator();list特有方法列表迭代器

Iterator迭代器只能對元素進行判斷,取出,刪除的操作,

如果想要其他的操作如新增,修改等,就需要使用其子介面,ListIterator

package pract;

import java.util.ArrayList;
import java.util.ListIterator;

public class ArrayListDemo {
	/**
	 *  12、一個ArrayList物件aList中存有若干個字串元素,現欲遍歷該ArrayList物件,
		刪除其中所有值為"abc"的字串元素,請用程式碼實現。
		思路:
		1,建立一個ArrayList物件 並存儲若干字元
		2,遍歷物件 刪除元素
	 * */

	public static void main(String[] args) {
		// 建立ArrayList物件
		ArrayList<String> al = new ArrayList<String>();
		al.add("addf");//新增若干元素。
		al.add("abc");
		al.add("adabcddf");
		al.add("abcd");
		al.add("abc");
		
		//用迭代器遍歷集合ArrayList,ListIterator是List特有迭代器
		ListIterator<String> li = al.listIterator();

		while(li.hasNext())//判斷集合是否有元素
		{
			String s = li.next();//獲取集合元素
			//當集合元素和adc相同時
			if(s.equals("abc"))
				li.remove();//在集合中刪除該元素

		}
		System.out.println(al);//列印結果:[addf, adabcddf, abcd]
	}

}

LinkedList:特有方法:

addFirst();addLast();新增元素

getFirst();getLast();

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

removeFirst();removeLast();

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

JDK1.6出現了替代方法。

offerFirst();offerLast();新增元素

peekFirst();peekLast();

獲取元素,但不刪除元素。如果集合中沒有元素,會返回null

pollFirst();pollLast();

獲取元素,但是元素被刪除。如果集合中沒有元素,會返回null

package pract;

import java.util.LinkedList;

public class LinkedListTest {
	/**
	 * 使用LinkedList模擬一個堆疊或者佇列資料結構。

		堆疊:先進後出  如同一個杯子。
		佇列:先進先出  如同一個水管。
		
		思路:用LinkedList模擬,先進先出
		1,用LinkedList的addFirst新增,因為每一次加入都是第一個元素,所以第一次加入的元素
		在記憶體中就變成最後一個,所以取出的時候用removeLast就會取出最後元素並刪除,下次還能去最
		後一個。先進後出同理也是一樣,只不過把取出方式變成先刪除第一個而已。
		*/

	public static void main(String[] args) {
		// 
		DuiLie dl = new DuiLie();//建立DuiLie物件
		dl.myAdd("java01");
		dl.myAdd("java02");//新增元素,底層呼叫LinkedList.addFirst()方法
		dl.myAdd("java03");
		dl.myAdd("java04");

		while(!dl.isNull())//判斷是否為空,底層呼叫LinkedList.isEmpty()方法
		{
			System.out.println(dl.myGet());
			//獲取元素,底層呼叫LinkedList.removeLast()刪除
		}
		
		DuZhan d2 = new DuZhan();
		d2.myAdd("zhangsan");
		d2.myAdd("lisi");
		d2.myAdd("wangwu");
		d2.myAdd("xiaoliu");

		while(!d2.isNull())
		{
			System.out.println(d2.myGet());
		}
	}

}
class DuiLie
{
	private LinkedList<Object> link;

	DuiLie()
	{//物件一初始化就創立LiskedList物件
		link = new LinkedList<Object>();
	}
	
	public void myAdd(Object obj)
	{
		link.addFirst(obj);//用LinkedList的addFirst加入
	}
	public Object myGet()
	{
		return link.removeLast();//用//用LinkedList的removeLast刪除
	}
	public boolean isNull()//判斷集合是否為空
	{
		return link.isEmpty();
	}

}
class DuZhan{
	private LinkedList<Object> link ;
	
	DuZhan(){
		link = new LinkedList<Object>();
	}
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
	public Object myGet()
	{
		return link.removeFirst();
	}
	public boolean isNull()
	{
		return link.isEmpty();
	}
}

程式執行結果:

java01

java02

java03

java04

xiaoliu

wangwu

lisi

zhangsan

Vector列舉就是Vector特有的取出方式。發現列舉和迭代器很像。其實列舉和迭代是一樣的。因為列舉的名稱以及方法的名稱都過長。所以被迭代器取代了。

Enumeration en = v.elements();

while(en.hasMoreElements()){

System.out.println(en.nextElement());

}

Set集合的功能和Collection是一致的。

HashSet元素需要複寫hashCode();如果hash值相同,還需要比較equalsHashCode()返回值是intequalsboolean

package pract;

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
	/**
	 *  往hashSet集合中存入自定物件
		姓名和年齡相同為同一個人,重複元素。
		
	 */
	public static void main(String[] args) {
		
		HashSet<People> hs = new HashSet<People>();

		hs.add(new People("a1",11));
		hs.add(new People("a2",12));
		hs.add(new People("a3",13));
		hs.add(new People("a3",13));
		//迭代器遍歷集合元素
		Iterator<People> it = hs.iterator();

		while(it.hasNext())//判斷集合是否有元素
		{
			People p = it.next();//獲取物件元素
			System.out.println(p.getName()+"::"+p.getAge());
			//輸出物件姓名和年齡
		}
	}
}
class People{//構造People類
	private String name;
	private int age;
	public People(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	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;
	}
	@Override
	public int hashCode() {//因為要儲存到HashSet中,所以需要覆蓋hashCode方法
		//返回姓名+年齡的雜湊值。
		return name.hashCode()+age*37;
	}
	@Override
	public boolean equals(Object obj) {//在HashSet中,hashCode值相同比較equals方法
		//如果比較的不是People物件,就返回不相等
		if(!(obj instanceof People))
			return false;

		People p = (People)obj;//將obj轉成People
		//比較姓名和年齡是否相等
		return this.name.equals(p.name) && this.age == p.age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}		
}

//輸出結果:
a3::13
a1::11
a2::12
//通過執行結果可以反映出雜湊表中的儲存是無序的。

TreeSet

排序的第一種方式:讓元素自身具備比較性。元素需要實現Comparable介面,覆蓋compareTo方法。也種方式也成為元素的自然順序,或者叫做預設順序。

TreeSet的第二種排序方式。當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。在集合初始化時,就有了比較方式。,實現Comparator介面,覆蓋compare方法

package pract;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {

	public static void main(String[] args) {
		//<Stu>是泛型。泛型格式:通過<>來定義要操作的引用資料型別。
		TreeSet<Stu> ts = new TreeSet<Stu>(new MyCompare());
		ts.add(new Stu("liming",12,80));
		ts.add(new Stu("zhangsan",11,90));
		ts.add(new Stu("lisi",20,70));
		ts.add(new Stu("wangwu",18,100));
		
		Iterator<Stu> it = ts.iterator();
		while(it.hasNext()){
			Stu  stu = it.next();
			System.out.println(stu);
		}
	}

}
class Stu implements Comparable<Stu>{//強制使Stu具備比較性
	private String name;
	private int age;
	private int score;
	public Stu(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}
	//實現compareTo方法,這個方法是按照年齡排序
	public int compareTo(Stu s){
		int num = new Integer(this.age).compareTo(s.age);
		if(num==0)
			num = this.name.compareTo(s.name);
		return num;
	}

	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;
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}
	
	@Override
	//我們以後定義類應該複寫hashCode和equals方法,保證類在雜湊表中也可以正確儲存。
	public int hashCode() {
		return name.hashCode()+age*37;
	}

	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof Stu))
			return false;
		Stu s = (Stu)obj;
		return this.name.equals(s.name)&&this.age==s.age;
	}

	@Override
	public String toString() {
		return "Stu [name=" + name + ", age=" + age + ", score=" + score + "]";
	}
	
}
class MyCompare implements Comparator<Stu>{//自定義比較器,按照姓名排序,姓名相同按照年齡排序
	public int compare(Stu s1,Stu s2){
		int num = s1.getName().compareTo(s2.getName());
		if(num==0){
			num = new Integer(s1.getAge()).compareTo(s2.getAge());
		}
		return num;
	}
}

//執行結果:

Stu [name=liming, age=12, score=80]

Stu [name=lisi, age=20, score=70]

Stu [name=wangwu, age=18, score=100]

Stu [name=zhangsan, age=11, score=90]

//分析,果然按照姓名排序了。

泛型好處

1.將執行時期出現問題ClassCastException,轉移到了編譯時期。,

方便於程式設計師解決問題。讓執行時問題減少,安全。,

2,避免了強制轉換麻煩。

泛型格式:通過<>來定義要操作的引用資料型別。

當泛型定義在方法上時候放在返回值前面。

3,什麼時候定義泛型類?

當類中要操作的引用資料型別不確定的時候,早期定義Object來完成擴充套件。現在定義泛型來完成擴充套件。

泛型可以定義在類上,方法上,介面上,還可以定義在靜態方法上:

如果靜態方法操作的應用資料型別不確定,可以將泛型定義在方法上。

package pract;

public class Demo<T> {//泛型定義在類上
	public  void show(T t)
	{
		System.out.println("show:"+t);
	}
	public <Q> void print(Q q)//泛型定義在方法上
	{
		System.out.println("print:"+q);
	}
	public  static <W> void method(W t)//泛型定義在靜態方法上
	{
		System.out.println("method:"+t);
	}
	//靜態方法不可以訪問類上定義的泛型。但是可以把泛型定義在方法上。
	public static void main(String[] args) {
		Demo<String> d = new Demo<String>();
		d.show("java");
		d.print(434);
		d.method("static");
	}

}

//執行結果:

show:java

print:434

method:static