1. 程式人生 > >Java常用物件API——集合(框架、Collection集合、List集合、Set集合)

Java常用物件API——集合(框架、Collection集合、List集合、Set集合)

集合框架

在這裡插入圖片描述

集合類

集合物件用於封裝特有資料,物件多了需要儲存,如果物件的個數不確定。 就使用集合容器進行儲存。

集合特點: 1,用於儲存物件的容器。 2,集合的長度是可變的。 3,集合中不可以儲存基本資料型別值。

集合容器因為內部的資料結構不同,有多種具體容器。 不斷的向上抽取,就形成了集合框架

框架的頂層Collection介面

Collection的常見方法

1,新增。 boolean add(Object obj): boolean addAll(Collection coll):

2,刪除。 boolean remove(object obj): boolean removeAll(Collection coll); void clear();

3,判斷: boolean contains(object obj): boolean containsAll(Colllection coll); boolean isEmpty():判斷集合中是否有元素。

4,獲取: int size(): Iterator iterator():取出元素的方式:迭代器。 該物件必須依賴於具體容器,因為每一個容器的資料結構都不同。 所以該迭代器物件是在容器中進行內部實現的。 對於使用容器者而言,具體的實現不重要,只要通過容器獲取到該實現的迭代器的物件即可, 也就是iterator方法。

Iterator介面就是對所有的Collection容器進行元素取出的公共介面。 其實就是抓娃娃遊戲機中的夾子!

常用方法使用演示:

   import java.util.ArrayList;
   import java.util.Collection;
		    			
			public class CollectionDemo {
			
				public static void main(String[] args) {
					Collection coll = new ArrayList();
					
			//		show(coll);
					
					Collection c1 = new ArrayList();
					Collection c2 = new ArrayList();
					show(c1,c2);
					
				}
				
				public static void show(Collection c1,Collection c2){
					
					//給c1新增元素。
					c1.add("abc1");
					c1.add("abc2");
					c1.add("abc3");
					c1.add("abc4");
					
					//給c2新增元素。
					c2.add("abc1");
					c2.add("abc2");
					c2.add("abc3");
					c2.add("abc4");
					c2.add("abc5");
					
					System.out.println("c1:"+c1);
					System.out.println("c2:"+c2);
					
					//演示addAll
					
			//		c1.addAll(c2);//將c2中的元素新增到c1中。
					
					
					//演示removeAll
			//		boolean b = c1.removeAll(c2);//將兩個集合中的相同元素從呼叫removeAll的集合中刪除。
			//		System.out.println("removeAll:"+b);
					
					//演示containsAll
			//		boolean b = c1.containsAll(c2);
			//		System.out.println("containsAll:"+b);
					
					//演示retainAll
					boolean b = c1.retainAll(c2);//取交集,保留和指定的集合相同的元素,而刪除不同的元素。
											//和removeAll功能相反 。
					System.out.println("retainAll:"+b);
					System.out.println("c1:"+c1);
					
					
				}
				
				public static void show(Collection coll){
					
					//1,新增元素。add.
					coll.add("abc1");
					coll.add("abc2");
					coll.add("abc3");
					System.out.println(coll);
					
					
					//2,刪除元素。remove
			//		coll.remove("abc2");//會改變集合的長度 
					
					//清空集合.
			//		coll.clear();
					
					System.out.println(coll.contains("abc3"));
					
					
					System.out.println(coll);
					
				}
			
			}

迭代器使用演示:

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

public class IteratorDemo {

	
	public static void main(String[] args) {

		Collection coll = new ArrayList();
		coll.add("abc1");
		coll.add("abc2");
		coll.add("abc3");
		coll.add("abc4");
		
//		System.out.println(coll);
		
		//使用了Collection中的iterator()方法。 呼叫集合中的迭代器方法,是為了獲取集合中的迭代器物件。
//		Iterator it = coll.iterator();		
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
		
		for(Iterator it = coll.iterator(); it.hasNext(); ){    //常用
			System.out.println(it.next());
		}
		
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());
//		System.out.println(it.next());//java.util.NoSuchElementException
		
	}

}

執行結果在這裡插入圖片描述 小結:it.next();用來取出集合中的下一個元素(it為某個集合物件) it.hasNext();用來判斷集合中是否還有下一個元素

Collection框架 |–List:有序(存入和取出的順序一致),元素都有索引(角標),元素可以重複。 |–Set:元素不能重複,無序。

List集合

特有的常見方法

有一個共性特點就是都可以操作角標 1,新增 void add(index,element); void add(index,collection);

2,刪除; Object remove(index): //返回值是被刪除的元素

3,修改: Object set(index,element);

4,獲取: Object get(index); int indexOf(object); int lastIndexOf(object); List subList(from,to);//包頭不包尾

由上看出,list集合可以完成對元素的增刪改查。

listIterator類

列表迭代器,它可以實現在迭代過程中完成對元素的增刪改查 舉例

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;


public class ListDemo2 {
public static void main(String[] args) {

	List list = new ArrayList();
//		show(list);
	
	
	list.add("abc1");
	list.add("abc2");
	list.add("abc3");
	
	System.out.println("list:"+list);
	ListIterator it = list.listIterator();//獲取列表迭代器物件
	//它可以實現在迭代過程中完成對元素的增刪改查。
	//注意:只有list集合具備該迭代功能.
	
	
	while(it.hasNext()){
		
		Object obj = it.next();
		
		if(obj.equals("abc2")){
			it.set("abc9");
			//it.add("abc9");
		}
	}
//		System.out.println("hasNext:"+it.hasNext());
//		System.out.println("hasPrevious:"+it.hasPrevious());
		
		
		while(it.hasPrevious()){              //逆序
			System.out.println("previous:"+it.previous());
		}
		System.out.println("list:"+list);
		
		
		
		
		
		/*Iterator it = list.iterator();    //這是異常舉例
		while(it.hasNext()){
			
			Object obj = it.next();//java.util.ConcurrentModificationException
							//在迭代器過程中,不要使用集合操作元素,容易出現異常。
						//可以使用Iterator介面的子介面ListIterator來完成在迭代中對元素進行更多的操作。 
			
			if(obj.equals("abc2")){
				list.add("abc9");
			}
			else
				System.out.println("next:"+obj);
		}
		System.out.println(list);
		*/


	}

	public static void show(List list) {
		
		list.add("abc1");
		list.add("abc2");
		list.add("abc3");
		list.add("abc4");
		
		Iterator it = list.iterator(); // 通用的取出方式
		while(it.hasNext()){
			System.out.println("next:"+it.next());
		}
		
		//list特有的取出元素的方式之一。
		
		for(int x=0; x<list.size(); x++){
			System.out.println("get:"+list.get(x));
		}
	}

}

List常用子類的特點

List: |–Vector:內部是陣列資料結構,是同步的。增刪,查詢都很慢! |–ArrayList:內部是陣列資料結構,是不同步的。替代了Vector。查詢的速度快。 |–LinkedList:內部是連結串列資料結構,是不同步的。增刪元素的速度很快。

Vector集合

陣列資料結構。增刪,查詢都很慢。

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;

public class VectorDemo {

	
	public static void main(String[] args) {

		Vector v = new Vector();
		
		v.addElement("abc1");
		v.addElement("abc2");
		v.addElement("abc3");
		v.addElement("abc4");
		
		Enumeration en = v.elements();   //返回此向量的列舉   此介面的功能與迭代器是重複的
		while(en.hasMoreElements()){
			System.out.println("nextelment:"+en.nextElement());
		}
		
		Iterator it = v.iterator();      //優先考慮Iterator介面,保證了閱讀性和簡單
		
		while(it.hasNext()){
			System.out.println("next:"+it.next());
		}
		
	}

 }

LinkedList

連結串列資料結構,增刪元素的速度很快。

import java.util.Iterator;
import java.util.LinkedList;
	
	public class LinkedListDemo {
    public static void main(String[] args) {

	LinkedList link = new LinkedList();
	
	link.addFirst("abc1");  //新增到表頭位置
	link.addFirst("abc2");
	link.addFirst("abc3");
	link.addFirst("abc4");
//		System.out.println(link);
//		System.out.println(link.getFirst());//獲取第一個但不刪除。
//		System.out.println(link.getFirst());
		
//		System.out.println(link.removeFirst());//獲取元素但是會刪除。
//		System.out.println(link.removeFirst());
		
	while(!link.isEmpty()){
		System.out.println(link.removeLast());
	}
	
	
		System.out.println(link);
//		Iterator it = link.iterator();
//		while(it.hasNext()){
//			System.out.println(it.next());
//		}
	}

}

練習:堆疊與佇列

  • 請使用LinkedList來模擬一個堆疊或者佇列資料結構。

  • 堆疊:先進後出 First In Last Out FILO

  • 佇列:先進先出 First In First Out FIFO

  • 我們應該描述這樣一個容器,給使用提供一個容器物件完成這兩種結構中的一種。

    package cn.itcast.p2.linkedlist.test;
    
    import java.util.LinkedList;
    
    
    
    	public class DuiLie {   //先進先出
    	private LinkedList link;
    
        public DuiLie() {
        	link = new LinkedList(); //使用建構函式來進行初始化
        }
        
        /**
         * 佇列的新增元素的功能。若改成棧,則addFirst即可
         */
        public void myAdd(Object obj) {
        	link.addLast(obj);
        }
        
        public Object myGet() {
        	return link.removeFirst();
        }
        
        public boolean isNull() {
        	return link.isEmpty();
        	}
         }	
    
package cn.itcast.p2.linkedlist.test;

import java.util.ArrayList;
public class LinkedTest {

public static void main(String[] args) {
	
		DuiLie dl = new DuiLie();
		
		dl.myAdd("abc1");
		dl.myAdd("abc2");
		dl.myAdd("abc3");
		dl.myAdd("abc4");
	
		while(!dl.isNull()){
			System.out.println(dl.myGet());
		}
	
	
	}
 }

1.6版本新特性

LinkedList:

addFirst(); addLast(): jdk1.6 offerFirst(); offetLast();

getFirst();.//獲取但不移除,如果連結串列為空,丟擲NoSuchElementException. getLast(); jdk1.6 peekFirst();//獲取但不移除,如果連結串列為空,返回null. peekLast():

removeFirst();//獲取並移除,如果連結串列為空,丟擲NoSuchElementException. removeLast();` jdk1.6 pollFirst();//獲取並移除,如果連結串列為空,返回null. pollLast();

ArrayList

package cn.itcast.p3.arraylist.test;

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

import cn.itcast.p.bean.Person;  //這是一個已經定義過的類

public class ArrayListTest {


	public static void main(String[] args) {
		Person p1 = new Person("lisi1",21);
		
		ArrayList al = new ArrayList();
		al.add(p1);
		al.add(new Person("lisi2",22));
		al.add(new Person("lisi3",23));
		al.add(new Person("lisi4",24));
		
		Iterator it = al.iterator();
		while(it.hasNext()){
//			System.out.println(((Person) it.next()).getName()+"::"+((Person) it.next()).getAge()); //不能在一次迴圈語句中用兩次next
			Person p = (Person) it.next();
			System.out.println(p.getName()+"--"+p.getAge());
		}
//		al.add(5);//al.add(new Integer(5)); //自動裝箱
	}
	

}

Set集合

Set:元素不可以重複,是無序。 Set介面中的方法和Collection一致。 常用子類特點: |–HashSet: 內部資料結構是雜湊表 ,是不同步的。 |–TreeSet:可以對Set集合中的元素進行排序。是不同步的。

HashSet

內部資料結構是雜湊表 ,是不同步的。

如何保證該集合的元素唯一性呢? 是通過物件的hashCode和equals方法來完成物件唯一性的。 如果物件的hashCode值不同,那麼不用判斷equals方法,就直接儲存到雜湊表中。 如果物件的hashCode值相同,那麼要再次判斷物件的equals方法是否為true。 如果為true,視為相同元素,不存。如果為false,那麼視為不同元素,就進行儲存。 記住:如果元素要儲存到HashSet集合中,必須覆蓋hashCode方法和equals方法。 一般情況下,如果定義的類會產生很多物件,比如人,學生,書,通常都需要覆蓋equals,hashCode方法。 建立物件判斷是否相同的依據。

演示:

package cn.itcast.p4.hashset.demo;

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

public class HashSetDemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		HashSet hs = new HashSet();
		
		hs.add("hehe");
//		hs.add("heihei");
		hs.add("hahah");
		hs.add("xixii");
		hs.add("hehe");   //由於元素唯一性,無法再存入
		
		Iterator it = hs.iterator();
		
		while(it.hasNext()){
			System.out.println(it.next());   不保證有序性
		}
	}

}

HashSet儲存自定義物件

往hashSet集合中儲存Person物件(帶有姓名和年齡引數)。如果姓名和年齡相同,視為同一個人。視為相同元素。這需要讓Person物件自定義一個hashCode方法。

		@Override
		public int hashCode() {         //自定義
	
			
			return name.hashCode()+age*27;
	
		}
		
		
		
		@Override
		public boolean equals(Object obj) {
			
			if(this == obj)
				return true;
			if(!(obj instanceof Person))
				throw new ClassCastException("型別錯誤");
			
	//		System.out.println(this+"....equals....."+obj);
			Person p = (Person)obj;
			
			
			
			return this.name.equals(p.name) && this.age == p.age;
		}

test部分

 	import java.util.HashSet;
	import java.util.Iterator;
	
	import cn.itcast.p.bean.Person;
	
	
	public class HashSetTest {
	
	
		public static void main(String[] args) {
	
			
			HashSet hs = new HashSet();
			
			/*
			 * HashSet集合資料結構是雜湊表,所以儲存元素的時候,
			 * 使用的元素的hashCode方法來確定位置,如果位置相同,在通過元素的equals來確定是否相同。
			 * 
			 */
			
			hs.add(new Person("lisi4",24));
			hs.add(new Person("lisi7",27));
			hs.add(new Person("lisi1",21));
			hs.add(new Person("lisi9",29));
			hs.add(new Person("lisi7",27));  //同一個人
			
			
			Iterator it = hs.iterator();
			
			while(it.hasNext()){
				Person p = (Person)it.next();
				System.out.println(p);
	//			System.out.println(p.getName()+"...."+p.getAge());
			}
		}
	
	}

在這裡插入圖片描述

練習

定義功能去除ArrayList中的重複元素。

public class ArrayListTest2 {
	
		
		public static void main(String[] args) {
			
	
	
			ArrayList al = new ArrayList();
			al.add(new Person("lisi1",21));
			al.add(new Person("lisi2",22));
			al.add(new Person("lisi3",23));
			al.add(new Person("lisi4",24));
			al.add(new Person("lisi2",22));
			al.add(new Person("lisi3",23));
			System.out.println(al);
			
			al = getSingleElement(al);
			
			
			System.out.println(al.remove(new Person("lisi2",22)));
			System.out.println(al);
			
	
		}
	

		public static ArrayList getSingleElement(ArrayList al) {
			
			//1,定義一個臨時容器。
			ArrayList temp = new ArrayList();
			
			//2,迭代al集合。
			Iterator it = al.iterator();
			
			while(it.hasNext()){
				Object obj = it.next();
				
				//3,判斷被迭代到的元素是否在臨時容器存在。
				if(!temp.contains(obj)){
					temp.add(obj);
				}
			}
			
			return temp;
		}
	

	}

當Person類中的equals方法沒有進行覆蓋時,執行結果如下: 在這裡插入圖片描述 當對Person類中的equals方法覆蓋時——

	@Override 	
	public boolean equals(Object obj) {
		 		if(this == obj) 			
		 			return true; 		
		 		if(!(obj instanceof Person)) 			
		 			throw new ClassCastException("型別錯誤");
		

		Person p = (Person)obj;   //對於該物件,應該比較的是姓名與年齡
		
		
		 		return this.name.equals(p.name) && this.age == p.age; 	}  

執行結果如下: 在這裡插入圖片描述 由此可以得出結論:使用contains與remove方法時,都是依賴於該物件的equals方法去判斷是否存在相同物件的。 當Person的equals方法沒有被覆蓋時,那麼就繼承了Object類的equals方法,則比較的是引用型別的變數所指向的物件的地址,在本例下,即使兩個物件的引數相同,但是由於地址不同,則並不會被判定為相同物件。

LinkedHashSet

當需要保證唯一與有序兼顧時,使用這個子類就行了。

TreeSet

可以對Set集合中的元素進行排序。是不同步的。

判斷元素唯一性的方式:就是根據比較方法的返回結果是否是0,是0,就是相同元素,不存。

TreeSet對元素進行排序的方式一: 讓元素自身具備比較功能,就需要實現Comparable介面。覆蓋compareTo方法(自然排序)。 如果不按照物件中具備的自然順序進行排序,或物件中不具備自然順序。怎麼辦? 可以使用TreeSet集合第二種排序方式二: 讓集合自身具備比較功能,定義一個類實現Comparator介面,覆蓋compare方法。將該類物件作為引數傳遞給TreeSet集合的建構函式。

方式一:實現Comparable介面,覆蓋compareTo方法

	//這是Person類的一部分
	@Override
	public int compareTo(Object o) {
		
		Person p = (Person)o;    
		
		int  temp = this.age-p.age;
		return temp==0?this.name.compareTo(p.name):temp;
		

		
	/*	if(this.age>p.age)         //有強轉,健壯性判斷
			return 1;
		if(this.age<p.age)
			return -1;	
		
		else{
			
			return this.name.compareTo(p.name);
		}*/  這是另一種寫法

Demo

public class TreeSetDemo {
	
		public static void main(String[] args) {
	
			TreeSet ts = new TreeSet();
			
			/*
			  以Person物件年齡進行從小到大的排序。
			
			 */
			
			ts.add(new Person("zhangsan",28));
			ts.add(new Person("lisi",21));
			ts.add(new Person("zhouqi",29));
			ts.add(new Person("zhaoliu",25));
			ts.add(new Person("wangu",24));
			
			Iterator it = ts.iterator();
			
			while(it.hasNext()){
				Person p = (Person)it.next();
				
				System.out.println(p.getName()+":"+p.getAge());
			}
		
		}
	
	
	
	}

執行結果在這裡插入圖片描述

方式二:Comparator比較器

覆蓋compare方法。

import java.util.Comparator;

import cn.itcast.p.bean.Person;
/**
 * 建立了一個根據Person類的name進行排序的比較器。
 */
public class ComparatorByName implements Comparator {

	@Override
	public int compare(Object o1, Object o2) {

		Person p1 = (Person)o1;
		Person p2 = (Person)o2;
		
		int temp = p1.getName().compareTo(p2.getName());
		
		return temp==0?p1.getAge()-p2.getAge(): temp;
//		return 1;//有序。
	}

}

TreeSet ts = new TreeSet(new ComparatorByName()); 將比較器類物件作為引數傳遞給TreeSet集合的建構函式。

示例:對字串進行長度排序

這種情況是不能使用字串的自然排序,所以要用到比較器。

import java.util.Comparator;

public class ComparatorByLength implements Comparator {  //比較器

	@Override
	public int compare(Object o1, Object o2) {
		
		String s1 = (String)o1;
		String s2 = (String)o2;
		
		int temp = s1.length()-s2.length();
		
		return temp==0? s1.compareTo(s2): temp;
	}

}
/* 
  • 對字串進行長度排序。 */

     	import java.util.Iterator;
     	import java.util.TreeSet;
     	
     	import cn.itcast.p5.comparator.ComparatorByLength;
     
     
     
     	public class TreeSetTest {
     	
     	/**
     	 * @param args
     	 */
     	public static void main(String[] args) {
     
     		TreeSet ts = new TreeSet(new ComparatorByLength());
     
     		ts.add("aaaaa");
     		ts.add("zz");
     		ts.add("nbaq");
     		ts.add("cba");
     		ts.add("abc");
     		
     		Iterator it = ts.iterator();
     		
     		while(it.hasNext()){
     			System.out.println(it.next());
     		}
     	}
     
     }