Java集合框架裏List子接口的contains()和Remove()方法剖析

————————————————————————————————————————
———————————————————————

List框架內容可以看這篇文章,很不錯

本文主要介紹一下:

關於ArrayList和LinkedList容器內部的

contains()方法 和 Remove()方法的內部實現機制。

總體來說就是:利用Object類的equals()方法。並進行重寫;
通過兩個小例子進行解釋更清晰一些:

案例一:實現去除ArrayList容器內的重複元素。

import java.util.*;//引入java包

	public static ArrayList signalElements(ArrayList al)
	{
		//定義臨時ArrayList容器
		ArrayList newal=new ArrayList();
		//遍歷傳入的集合
		Iterator it=al.iterator();

		while(it.hasNext())
		{
			Object obj=it.next();
			
//----------contains()方法使用的是obj的equals()方法!(先忽略)--------------------------

			if(!newal.contains(obj))
				newal.add(obj);
		}
		return newal;
	}

案例二:實現自定義對象存入到ArrayList容器中,並去除重複元素。

假設定義一個包含姓名和年齡的Person類

class Person
{
	private String name;
	private int age;
	//假設函數一初始化就指定姓名和年齡
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	//這裏只寫了get方法,用於獲取。開發一般get和set都寫
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

主函數:

class CollectionListDemo 
{
	public static void main(String[] args) 
	{
		//創建一個ArrayList集合
		ArrayList al=new ArrayList();
		//添加元素
		
//------集合添加進去的實際上是一個地址值,並不是元素實體------------------------

		al.add(new Person("zhangsan01",20));
		al.add(new Person("lishi01",21));
		al.add(new Person("zhangsan01",22));
		al.add(new Person("lishi01",21));

//------實現取對象元素的屬性,即姓名,年齡------------------------------------
//-------標籤:001------這行等下要添加代碼-----------------------------------
//-------標籤:002------這行等下要添加代碼-----------------------------------

		//創建迭代器
		Iterator it=al.iterator();
		while(it.hasNext())
		{
			System.out.println(it.next().getName()+"......"+it.next().getAge());
			/*
			這句話有兩處錯誤:
				1.每使用一次it.next(),指針便會往下走,即獲取到的是下一個元素。
			所以第一次打印的結果爲zhangsan01這個姓名和lishi01的年齡21
				2.實際上這句話會直接報錯。根本不會打印結果。原因:
			迭代器作爲對集合遍歷,由於集合內存入的元素類型並不一定相同。
			所以迭代器返回的結果爲Object類型的,在使用it.next()時
			返回了一個Object類對象,但是Object對象並不存在getName()方法。
			而只有Person類纔有該方法。所以涉及到多態:
			正確使用:
						Object obj = it.next();
						Person p = (Person)obj;
						System.out.println(p.getName()+"......"+p.getAge());
			*/
		}
	}
}
到這裏我們僅僅實現了添加自定義對象。接下來實現去除重複值:

把案例一的代碼拷貝到主函數所在類CollectionListDemo中。
並在主函數中加入:

al = signalElements(al);
位置:放在 “標籤:001” 那裏(找不到用Ctrl—F查找)
運行結果:
	zhangsan01......20
	lishi01......21
	zhangsan01......22
	lishi01......21
發現並沒有去除掉重複元素。

查其原因即可明白,其一直都有走下面這句代碼。

if(!newal.contains(obj))

我們再回去看ArrayList的add()方法:發現其實際存的是地址值。每new一個對象,就會開闢一塊空間。就會有一個地址值。所以這四個加入的元素有四個不同的地址。而我們判斷包含contains(),實際使用的是Object類的equals()方法(Object類的equals()比較的是地址值,地址相同才返回true,否則返回false)。所以上述操作並沒有刪除掉成功。

解決辦法:
重寫equals()方法。讓其比較內部元素而不是地址值。

在Person類裏重寫Object的equals()方法

public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))//防止你隨便拿一個其他類,比如Student類來和Person類進行比較,沒意義
			return false;
		Person p=(Person)obj;
		return this.name.equals(p.name)&&this.age==p.age;//這句話裏的equals是String類的equals方法
	}

這個方法會被 contains() 方法自動調用。

jdk API裏關於contains(Object o)方法的描述:

public boolean contains(Object obj)
//如果此列表中包含指定的元素,則返回 true。
更確切地講,當且僅當此列表包含至少一個滿足 (obj==null ? e==null : obj.equals(e)) 的元素 e 時,則返回 true。 

//////////////////////////////////////////////////////////// A /////////////////////////////////
s
Tip:
看見////////////////裏的 'A' 字符上面的 "obj" 了嗎。再看案例一里面的contains()方法。就更容易明白了。

到這裏,算是講完了contains()方法,接下來看Remove()方法。

比如我們想要刪除如下元素

zhangsan01......20

在”標籤:002“那裏寫這句話

System.out.println("移除元素:"+remove(new Preson("zhangsan01",20)));

前提:把重寫的equals()註釋掉

運行結果爲:
	移除元素:false

原因:移除的是個對象,利用Object類的equals()方法去判斷地址值,找不到相同的地址值。所以不可能刪掉。再把重寫的equals()取消註釋,就可以移除成功了。

下一篇:關於集合框架的Set接口的常用子接口的應用

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