Java集合的使用
一、Java集合的概念
java集合又稱爲java容器,主要用於在程序中存放對象,而且只能存放對象或者集合,不能存放基本數據類型。
二、容器API
J2SDK所提供的容器API位於java.util包內,集合API的類圖結構如下圖所示:
其中,Collection集合是一個一個的往裏邊裝,圖中的“重複”指的是兩個對象之間equals,Map這種容器是一對一對的往裏邊裝。
三、Collection接口
- Set和List分別定義了存儲方式,Set中的數據對象沒有順序且不可以重複,List中的數據對象有順序且可以重複。
- Map接口定義了存儲“鍵——值映射對”的方法
- Collection接口中所定義的方法:
int size//裝了多少個元素或者對象
boolean isEmpty()//是否爲空
void clear()//清空
boolean contains(Object element)//是否包含某個對象(包含的意思是傳遞的參數equals某一個內部的元素)
boolean add(Object element)//添加對象
boolean remove(Object element)//刪除對象
Iterator iterator//迭代器
boolean containsAll(Collection c)//是不是包含一個集合裏面的所有元素
boolean addAll(Collection c)//添加一個集合
boolean removeAll(Collection c)//刪除集合
boolean retainAll(Collection c)//求當前集合類和集合c的交集
Object[] toArray()//把裏面裝的每個對象全部轉化爲一個Object類型的數組
四、equals方法和hashcode方法的重寫
容器類對象在調用remove、contains等方法時需要比較對象是否相等,這會涉及到對象類型的equals方法和hashcode方法;對於自定義的類型,需要重寫equals和hashcode方法以實現自定義的對象相等規則。
注意:相等的對象應該具有相等的hashcode,重寫equals方法必須重寫hashcode方法。當對象在Map裏面作爲一對往Map裏面裝,這個對一個叫“鍵(key)”,一個叫“值(value)”,當這個對象作爲“鍵”的時候,hashcode是有用的。總而言之,就是重寫對象的equals方法必須重寫對象的hashcode方法,兩個對象equals,則必須具有相同的hashcode(hash碼)。
示例如下:
public class BaseContainer {
public static void main(String[] args) {
Collection c = new HashSet();
c.add("hello");
c.add(new Name("f1","l1"));
c.add(new Integer(100));
c.remove("hello");
c.remove(new Integer(100));
System.out.println(c.remove(new Name("f1","l1")));
System.out.println(c);
}
}
class Name{
private String firstName;
private String lastName;
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Name{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
/**
* 重寫equals方法
* @param obj 對象
* @return 兩個對象的比較結果,只有“我的名字”等於你傳遞給我的name對象的名字才返回true
*/
@Override
public boolean equals(Object obj) {
if(obj instanceof Name){
Name name = (Name) obj;
return firstName.equals(name.firstName)
&& lastName.equals(name.lastName);
}
return super.equals(obj);
}
/**
* 重寫hashcode方法
* @return 暫時使用字符串的hashcode方法(也可以自己實現,但是稍微複雜,可以自己研究下)
*/
@Override
public int hashCode() {
return firstName.hashCode();
}
}
輸出結果:
由於String類和Integer類已經重寫了equals和hashcode方法,故執行remove方法,會比較傳入的對象和集合中的對象是否equals,如果equals,則將集合中的元素移除,而Name類,如果不重寫equals方法和hashcode方法,則代碼執行的結果如下圖所示:
五、Iterator接口
- 所有實現了Collection接口的容器類都有一個iterator方法用以返回一個實現了iteration接口的對象。
- iterator對象稱作迭代器,用以方便的實現對容器內元素的遍歷操作。
- iterator接口定義瞭如下方法:
boolean hasNext();//判斷遊標右邊是否有元素
Object next();//返回遊標右邊的元素並將遊標移動到下一個位置
void remove();//刪除遊標左邊的元素,在執行完next之後該操作只能執行一次
- iterator對象的remove方法是在迭代過程中刪除元素的唯一安全的方法。
總之,iterator就是一個統一的來遍歷collection裏面所有元素的方法。
示例如下:
public class IteratorTest {
public static void main(String[] args) {
Collection c = new HashSet();
c.add(new Name("f1","l1"));
c.add(new Name("f2","l2"));
c.add(new Name("f3","l3"));
Iterator iterator = c.iterator();
while (iterator.hasNext()){
Name name = (Name) iterator.next();
if(name.equals(new Name("f1","l1"))){
iterator.remove();
}
}
System.out.print(c);
}
}
class Name {
private String firstName;
private String lastName;
public Name(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Name{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
/**
* 重寫equals方法
*
* @param obj 對象
* @return 兩個對象的比較結果,只有“我的名字”等於你傳遞給我的name對象的名字才返回true
*/
@Override
public boolean equals(Object obj) {
if (obj instanceof Name) {
Name name = (Name) obj;
return firstName.equals(name.firstName)
&& lastName.equals(name.lastName);
}
return super.equals(obj);
}
/**
* 重寫hashcode方法
*
* @return 暫時使用字符串的hashcode方法(也可以自己實現,但是稍微複雜,可以自己研究下)
*/
@Override
public int hashCode() {
return firstName.hashCode();
}
}
輸出結果如下:
可以看到成功刪除了名字爲f1,l1的對象(因爲使用的hashset集合,有可能輸出的順序和上面的不一致),需要注意的是在邊遍歷邊刪除多個集合元素過程中不能使用for循環或者增強for循環,因爲在刪除過程中,集合的元素個數已經發生了變化,而使用iterator可以正常刪除元素,使用for循環倒序遍歷也可以實現元素的刪除。無論是使用哪種方式,刪除一個對象都必須要重寫equals方法和hashcode方法,否則無法刪除元素!