一、集合框架
爲什麼出現集合類:
面嚮對象語言對事物的體現都是以對象的形式,所以爲了方便對多個對象的操作,就對對象進行存儲,集合就是存儲對象最常用的一種方式。
數組和集合類同是容器,有何不同:
數組雖然也可以存儲對象,但長度是固定的;集合長度是可變的。
數組中可以存儲基本數據類型,集合只能存儲對象。
集合類的特點:
集合只用於存儲對象,集合長度是可變的,集合可以存儲不同類型的對象。
二、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());
}
}
底層使用的是鏈表數據結構。特點:增刪速度很快,查詢稍慢。
特有方法:
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;
}
}
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;
}
}
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());
}
}
}
當元素自身不具備比較性時,或者具備的比較性不是所需要的。這時就需要讓集合自身具備比較性。在集合
初始化時,就有了比較方式。定義了比較器,將比較器對象作爲參數傳遞給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;
}
}
當兩種排序都存在時,以比較器爲主。