黑馬程序員_JAVA_集合框架(一)

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------


一、集合框架

爲什麼出現集合類:

        面嚮對象語言對事物的體現都是以對象的形式,所以爲了方便對多個對象的操作,就對對象進行存儲,集合就是存儲對象最常用的一種方式。


數組和集合類同是容器,有何不同:

        數組雖然也可以存儲對象,但長度是固定的;集合長度是可變的。

數組中可以存儲基本數據類型,集合只能存儲對象。


集合類的特點:

        集合只用於存儲對象,集合長度是可變的,集合可以存儲不同類型的對象。

 

二、Collection接口

集合類實現的接口,該接口定義了所有集合了的共性方法。集合中存儲的都是對象的引用(地址)。

Collection接口中的常見操作:

1、添加元素

         add(Objectobj); //add方法的參數類型是Object。以便於接收任意類型對象。

2、刪除元素

         remove(Objectobj);

         removeAll(另一集合);//調用者只保留另一集合中沒有的元素。

         clear();//清空集合

3、判斷元素

        contains(Objectobj);//判斷是否存在obj這個元素

        isEmpty();//是否爲空

4、獲取個數,集合長度

         size();

5、取交集

         retainAll(另一集合);//調用者只保留兩集合的共性元素。


迭代(Iterator

迭代是取出集合中元素的一種方式。

        對於集合的元素取出這個動作:當不足以用一個函數來描述,需要用多個功能來體現,所以就將取出這個動作封裝成一個對象來描述。就把取出方式定義在集合的內部,這樣取出方式就可以直接訪問集合內部的元素。那麼取出方式就被定義成了內部類。

         這些內部類都符合一個規則(或者說都抽取出來一個規則)。該規則就是Iterator。通過一個對外提供的方法:iterator();,來獲取集合的取出對象。

         因爲Collection中有iterator方法,所以每一個子類集合對象都具備迭代器。

 

2、迭代的常見操作

        hasNext();//有下一個元素,返回真

        next();//取出下一個元素

        remove();//移除


3、迭代注意事項

迭代器在Collcection接口中是通用的,它替代了Vector類中的Enumeration(枚舉)

迭代器的next方法是自動向下取元素,要避免出現NoSuchElementException

迭代器的next方法返回值類型是Object,所以要記得類型轉換。


Collection接口常見的子接口:

List接口:元素是有序的,元素可以重複。因爲該集合體繫有索引。

Set接口元素是無序的,元素不可以重複。


三、List接口類

元素是有序的,元素可以重複。因爲該集合體繫有索引。

子類:

        ArrayList:底層的數據結構使用的是數組結構。特點:查詢速度很快。但是增刪稍慢。線程不同步。

        LinkedList:底層使用的是鏈表數據結構。特點:增刪速度很快,查詢稍慢。

        Vector:底層是數組數據結構。線程同步。被ArrayList替代了。


List的特有方法:

1、增加

        booleanadd(index,element);//指定位置添加元素

        BooleanaddAll(index,Collection);//在指定位置增加給定集合中的所有元素,若省略位置參數,則在當前集合的後面依次添加元素

2、刪除

        Booleanremove(index);//刪除指定位置的元素

3、修改

        set(index,element);//修改指定位置的元素。

4、查找

        get(index);//通過角標獲取元素

        subList(from,to);//獲取部分對象元素

注意:List集合判斷元素是否相同,移除等操作,依據的是元素的equals方法。


ListIterator接口

List集合特有的迭代器ListIterator,是Iterator的子接口。 

在迭代時,不可以通過集合對象的方法操作集合中的元素,因爲會發生ConcurrentModificationException異常。所以,在迭代器時,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能對元素進行判斷,取出,刪除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。該接口只能通過List集合的listIterator方法獲取。

特有方法:

       add(obj);//增加

        set(obj);//修改

        hasPrevious();//判斷前面有沒有元素

        previous();//取前一個元素

枚舉Enumeration:

特有方法:

         addElement(obj);//添加元素

         Enumeration elements();//相當於Iterator方法

         hasMoreElements();//判斷是否還有下一個元素

         nextElements();//獲取下一個元素

public static void main(String[] args) {
	Vector v = new Vector();
	v.add("java01");
	v.add("java02");
	v.add("java03");
	Enumeration en = v.elements();
	while(en.hasMoreElements())
	{
		System.out.println(en.nextElement());
	}
}


LinkedList類:

        底層使用的是鏈表數據結構。特點:增刪速度很快,查詢稍慢。

特有方法:

1、增加

        addFirst();// 添加元素到集合的首部

        addLast();// 添加元素到集合的尾部

2、獲取

        //獲取元素,但不刪除元素,如果集合中沒有元素,則拋出異常。

        getFirst();// 獲取集合中的首元素

        getLast();// 獲取集合中的爲元素

3、刪除

        //獲取元素,並刪除元素如果集合中沒有元素,則拋出異常。

        removeFirst();// 刪除集合中的首元素

        removeLast();// 刪除集合中的尾元素

JDK1.6以後,出現了替代方法。

1、增加

        offFirst();

        offLast();

2、獲取

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

        peekFirst();

        peekLast();

3、刪除

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

        pollFirst();

        pollLast();

/*
使用LinkedList模擬一個堆棧或者隊列數據結構。

堆棧:先進後出  如同一個杯子。
隊列:先進先出 First in First out  FIFO 如同一個水管。

 */
import java.util.*;

class LinkedListTest {
	public static void main(String[] args) {
		LinkedList l = new LinkedList();
		l.addFirst("java01");
		l.addFirst("java02");
		l.addFirst("java03");
		l.addFirst("java04");
		l.addFirst("java05");

		// 堆棧輸出
		// stack(l);
		// 隊列輸出
		queue(l);
	}

	// 堆棧
	public static void stack(LinkedList l) {
		while (!l.isEmpty()) {
			sop(l.removeFirst());
		}
	}

	// 隊列
	public static void queue(LinkedList l) {
		while (!l.isEmpty()) {
			sop(l.removeLast());
		}
	}

	// 輸出
	public static void sop(Object obj) {
		System.out.println(obj);
	}
}

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

//去除ArrayList集合中的重複元素
class ArrayListTest {

	public static void sop(Object obj) {
		System.out.println(obj);
	}

	public static void main(String[] args) {
		ArrayList al = new ArrayList();// 初始化一個ArrayList對象
		// 添加元素
		al.add("java01");
		al.add("java02");
		al.add("java01");
		al.add("java02");
		al.add("java01");

		sop(al);// 打印原集合
		al = singleElement(al);
		sop(al);// 打印去掉重複元素的集合
	}

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


四、Set集合

1、Set接口類:

元素是無序(存入和取出的順序不一定一致),元素不可以重複。Set集合的功能和Collection是一致的。


常見的子類:     

HashSet:底層數據結構是哈希表。線程不同步。 

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


2、HashSet類:

HashSet:底層數據結構是哈希表。是線程不安全的。不同步。

HashSet保證元素的唯一性:

1、是通過元素的兩個方法,hashCode和equals來完成。

2、如果元素的HashCode值相同,纔會判斷equals是否爲true。

3、如果元素的hashcode值不同,不會調用equals。

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

import java.util.HashSet;
import java.util.Iterator;
class HashSetTest {
	public static void sop(Object obj) {
		System.out.println(obj);
	}

	public static void main(String[] args) {
		HashSet hs = new HashSet();// 定義一個HashSet

		// 向這個集合中添加自定義元素
		hs.add(new Person("a1", 11));
		hs.add(new Person("a2", 12));
		hs.add(new Person("a3", 13));

		// 遍歷這個集合
		Iterator it = hs.iterator();

		// 打印集合中的內容
		while (it.hasNext()) {
			Person p = (Person) it.next();
			sop(p.getName() + "::" + p.getAge());
		}
	}
}

class Person {
	private String name;// 人的屬性
	private int age;

	Person(String name, int age) {
		this.name = name;
		this.age = age;
	}

	// 覆蓋hashCode值和equals方法
	public int hashCode() {
		System.out.println(this.name + "....hashCode");
		return name.hashCode() + age * 37;
	}

	// 如果姓名和年齡相同就爲同一個人
	public boolean equals(Object obj) {

		if (!(obj instanceof Person))
			return false;

		Person p = (Person) obj;
		System.out.println(this.name + "...equals.." + p.name);

		return this.name.equals(p.name) && this.age == p.age;
	}

	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}
}


3、TreeSet類:

1、底層的數據結構爲二叉樹結構

        2、可對Set集合中的元素進行排序,默認的排序方式是自然順序


兩種排序方式:

1、自然排序

讓元素自身具備比較性。元素需要實現Comparable接口,覆蓋compareTo方法。

import java.util.*;
//學生類
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;
	}

	// 複寫hashCode以便HashSet集合調用
	public int hashCode() {
		return name.hashCode() + age;
	}

	// 複寫equals以便HashSet集合和集合中一些比較方法調用
	public boolean equals(Object obj) {
		if (!(obj instanceof Student))
			throw new RuntimeException();
		Student s = (Student) obj;
		return this.name.equals(s.name) && this.age == s.age;
	}

	// 複寫compareTo以便TreeSet集合調用
	public int compareTo(Object obj) {
		Student s = (Student) obj;
		if (this.age == s.age)
			return this.name.compareTo(s.name);
		return this.age - s.age;
	}
}

class TreeSetTest {
	public static void main(String[] args) {
		TreeSet<Student> t = new TreeSet<Student>();
		t.add(new Student("stu1", 12));
		t.add(new Student("stu4", 2));
		t.add(new Student("stu2", 12));
		t.add(new Student("stu3", 12));
		t.add(new Student("stu6", 22));

		for (Iterator<Student> it = t.iterator(); it.hasNext();) {
			Student s = it.next();
			System.out.println(s.getName() + "....." + s.getAge());
		}
	}
}


2、比較器排序

當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。在集合

初始化時,就有了比較方式。定義了比較器,將比較器對象作爲參數傳遞給TreeSet集合的構造函數。

實現方式:定義一個類,實現Comparator接口,覆蓋compare方法。

/*
需求:
往TreeSet集合中存儲自定義對象學生。
按照學生的年齡進行排序。
 */
import java.util.*;
//學生類
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;
	}

	// 複寫hashCode以便HashSet集合調用
	public int hashCode() {
		return name.hashCode() + age;
	}

	// 複寫equals以便HashSet集合和集合中一些比較方法調用
	public boolean equals(Object obj) {
		if (!(obj instanceof Student))
			throw new RuntimeException();
		Student s = (Student) obj;
		return this.name.equals(s.name) && this.age == s.age;
	}

	// 複寫compareTo以便TreeSet集合調用
	public int compareTo(Object obj) {
		Student s = (Student) obj;
		if (this.age == s.age)
			return this.name.compareTo(s.name);
		return this.age - s.age;
		// return new Integer(this.age).compareTo(new Integer(s.age));
	}
}

class TreeSetTest {
	public static void main(String[] args) {
		TreeSet<Student> t = new TreeSet<Student>(new LenCompare());
		t.add(new Student("stu1", 12));
		t.add(new Student("stu4", 2));
		t.add(new Student("stu2", 12));
		t.add(new Student("stu3", 12));
		t.add(new Student("stu6", 22));

		for (Iterator<Student> it = t.iterator(); it.hasNext();) {
			Student s = it.next();
			System.out.println(s.getName() + "....." + s.getAge());
		}
	}
}

// 定義一個比較器,以姓名長度爲主要比較
class LenCompare implements Comparator<Student> {
	public int compare(Student s1, Student s2) {
		int num = new Integer(s1.getName().length()).compareTo(new Integer(s2
				.getName().length()));
		if (num == 0) {
			return new Integer(s1.getAge()).compareTo(s2.getAge());
		}
		return num;
	}
}
當兩種排序都存在時,以比較器爲主。

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