1. 程式人生 > >JavaSE之Collection集合

JavaSE之Collection集合

Collection集合

  • java.util.Collection 集合

    集合可以儲存一組元素,並且提供了操作元素的相關方法。

  • 常用的子介面:

    • java.util.List 線性表 可重複 並且有序
    • java.util.Set 不可重複
    • 是否重複指的是元素是否可以重複,而判定是否重複的標準是依靠元素自身equals比較的結果。
public class CollectionDemo {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		/*
		 * boolean add(E e)
		 * 將給定元素新增到集合當中,當成功新增後方法
		 * 會返回true,新增失敗返回false
		 */
c.add("one"); c.add("two"); c.add("three"); c.add("four"); c.add("five"); System.out.println(c); /* * int size() * 獲取當前集合元素個數 */ int size = c.size(); System.out.println("size:"+size); /* * boolean isEmpty() * 判斷當前集合是否為空集(不含有任何元素) */ boolean isEmpty = c.isEmpty
(); System.out.println("是否為空集:"+isEmpty); /* * void clear() * 清空集合 */ c.clear(); System.out.println("集合已清空"); System.out.println("size:"+c.size()); System.out.println("isEmpty:"+c.isEmpty()); System.out.println(c); } }
  • 集合只能存放引用型別元素,並且儲存的元素的引用(地址)

    public class CollectionDemo2
    { public static void main(String[] args) { Collection c = new ArrayList(); Point p = new Point(1, 2); c.add(p); System.out.println("p:"+p); System.out.println("c:"+c); p.setX(2); System.out.println("p:"+p); System.out.println("c:"+c);//[(2,2)] } }
  • 集合操作

    public class CollectionDemo3 {
    	public static void main(String[] args) {
    		Collection c1 = new ArrayList();
    		c1.add("java");
    		c1.add("c");
    		c1.add("c++");
    		
    		Collection c2 = new ArrayList();
    		c2.add("android");
    		c2.add("ios");
    	
    		/*
    		 * boolean addAll(Collection c)
    		 * 新增完畢後,當前集合元素髮生改變則返回true
    		 */
    		c1.addAll(c2);
    		System.out.println("c1:"+c1);
    		
    		Collection c3 = new ArrayList();
    		c3.add("java");
    		c3.add("ios");
    //		c3.add("php");
    		/*
    		 * boolean containsAll(Collection c)
    		 * 判斷當前集合是否包含給定集合中的所有元素
    		 */
    		boolean contains = c1.containsAll(c3);
    		System.out.println("全包含:"+contains);
    
    		/*
    		 * boolean removeAll(Collection c)
    		 * 刪除當前集合與給定集合的公有元素
    		 */
    		c1.removeAll(c3);
    		System.out.println("c1:"+c1);	
    	}
    }
    
    
  • boolean contains(Object o) 判斷當前集合是否包含給定元素

    public class ContainsDemo {
    	public static void main(String[] args) {
    		Collection c = new ArrayList();
    		c.add(new Point(1, 2));
    		c.add(new Point(3, 4));
    		c.add(new Point(5, 6));
    		System.out.println(c);		
    		Point p = new Point(1, 2);
    		/*
    		 * contains的判定標準是看給定的物件p是否與
    		 * 集合現有元素存在equals比較為true的,若有
    		 * 則認為包含,否則為不包含。
    		 * 所以元素equals方法決定這集合判斷包含的結果
    		 */
    		boolean contains = c.contains(p);
    		System.out.println("包含:"+contains);
    		
    		
    	}
    }
    
  • 遍歷 Collection提供了統一的遍歷集合的方式:迭代器模式 對應方法: Iterator iterator( ) 該方法可以返回一個用於遍歷當前集合的迭代器

    public class IteratorDemo {
    	public static void main(String[] args) {
    		Collection c = new ArrayList();
    		c.add("one");
            c.add("#");
            c.add("two");
            c.add("#");
    		c.add("three");
    		c.add("#");
    		c.add("four");
    		c.add("#");
    		c.add("five");
    		System.out.println(c);
    		
    		//獲取迭代器
    		Iterator it = c.iterator();
    		/*
    		 * boolean hasNext()
    		 * 判斷集合是否還有下一個元素可以迭代。
    		 * 問的過程
    		 */
    		while(it.hasNext()){
    			/*
    			 * E next()
    			 * 通過迭代器獲取集合下一個元素。
    			 * 取的過程
    			 */
    			String str = (String)it.next();
    			System.out.println(str);
    			/*
    			 * 在遍歷的過程中刪除#操作
    			 * 需要注意:
    			 * 迭代器有一個要求,就是在遍歷的過程中不得
    			 * 使用集合的方法增刪元素,否則會丟擲異常。
    			 * 可以通過迭代器自身提供的remove方法刪除
    			 * 元素。該方法不需要傳入引數,刪除的是通過
    			 * next方法取出的元素。
    			 */
    			if("#".equals(str)){
    				it.remove();
    			}
    		}
    		
    		System.out.println(c);
    	}
    }
    
  • 增強for迴圈,也稱為新迴圈或for each 新迴圈是用來遍歷集合或陣列使用的,所以功能上不取代傳統for迴圈的工作,並且該特性是編譯器認可,而非虛擬機器認可。編譯器最終會將使用新迴圈遍歷改為傳統遍歷方式。

    public class NewForDemo1 {
    	public static void main(String[] args) {
    		String[] array = {"one","two","three","four"};
    		for(int i=0;i<array.length;i++){
    			String str = array[i];
    			System.out.println(str);
    		}
    		/*
    		 * 最終編譯器會將程式碼改編為普通for迴圈遍歷方式
    		 */
    		for(String str : array){
    			System.out.println(str);		
    		}
    		
    	}
    }
    
    public class NewForDemo2 {
    	public static void main(String[] args) {
    		Collection c = new ArrayList();
    		c.add("one");
    		c.add("two");
    		c.add("three");
    		c.add("four");
    		c.add("five");
    		System.out.println(c);
    		/*
    		 * 新迴圈遍歷集合最終會被編譯器改編為迭代器遍歷
    		 * 所以在使用新迴圈遍歷集合的過程中不要通過集合
    		 * 的方法增刪元素。
    		 */
    		for(Object o : c){
    			String str = (String)o;
    			System.out.println(str);
    		}
    	}
    }
    
  • 刪除元素

    public class RemoveDemo {
    	public static void main(String[] args) {
    		Collection c = new ArrayList();
    		c.add(new Point(1, 2));
    		c.add(new Point(3, 4));
    		c.add(new Point(5, 6));
    		System.out.println(c);
    		
    		Point p = new Point(1, 2);
    		/*
    		 * 刪除也是刪除集合中與給定元素equals比較為true的元素,
    		 * 對於List而言,重複元素只刪除第一個
    		 */
    		c.remove(p);
    		System.out.println(c);
    	}
    }
    
  • 集合的執行緒安全

    集合的工具類Collections可以將現有的集合轉換為一個執行緒安全的,對於集合自身的操作如:add,

    remove等都可以保證併發安全。但是API手冊也有說明,一個併發安全的集合也不與使用迭代器遍歷操作做互斥,這意味著併發操作中遍歷與集合自身操作並非併發安全的,需要自行維護互斥關係。

    List的常用實現類:ArrayList,LinkedList都不是執行緒安全的,可以通過Collections將List轉換為執行緒安全的

    public class SyncCollectionDemo {
    	public static void main(String[] args) {
    		List<String> list = new ArrayList<String>();
    		list.add("one");
    		list.add("two");
    		list.add("three");
    		System.out.println(list);
    		
    		list = Collections.synchronizedList(list);
    		System.out.println(list);
    		
    		//HashSet也不是執行緒安全的  
    		Set<String> set = new HashSet<String>(list);
    		set = Collections.synchronizedSet(set);
    		System.out.println(set);
    	}
    }
    
  • 泛型

    泛型是JDK1.5之後推出的另一個特性,泛型也稱為引數化型別,指在使用某個類時為其屬性,方法引數,方法返回值 的型別指定實際型別。這在實際開發中可以大大提高程式碼的靈活度。

    泛型應用最廣的地方就是集合,用來約束集合的元素型別。泛型的實際型別為Object,當不指定泛型時,預設就使用原型Object。

    泛型允許呼叫者使用時決定一個類中屬性,引數,返回值等的型別,從而提高程式碼的靈活性。

    public class Type<T> {
    	private T x;
    	private T y;
    	
    	public Type(T x, T y) {
    		super();
    		this.x = x;
    		this.y = y;
    	}
    	public T getX() {
    		return x;
    	}
    	public void setX(T x) {
    		this.x = x;
    	}
    	public T getY() {
    		return y;
    	}
    	public void setY(T y) {
    		this.y = y;
    	}
    	
    	@Override
    	public String toString() {
    		return "("+x+","+y+")";
    	}
    }
    
    public class TypeDemo {
    	public static void main(String[] args) {
    		//建立集合時通過泛型約束集合的元素型別
    		Collection<String> c = new ArrayList<String>();
    		c.add("one");//此時集合只能存放String
    		c.add("two");
    		c.add("three");
    		c.add("four");
    		System.out.println(c);
    		//獲取迭代器時也通過泛型告知迭代器元素型別
    		Iterator<String> it = c.iterator();
    		while(it.hasNext()){
    			//獲取元素時無需再造型
    			String str = it.next();
    			System.out.println(str);
    		}
    		//新迴圈也可以直接使用String接收集合元素了
    		for(String str:c){
    			System.out.println(str);
    		}
    		
    	}
    }
    
    //泛型應用
    public class TypeDemo2 {
    	public static void main(String[] args) {
    		/*
    		 * Type中的x,y都是泛型<T>,而泛型的實際型別是
    		 * Object,所以x,y實際上就是Object型別
    		 *
    		 * 在使用時,指定T為Integer,那麼編譯器會依靠該型別
    		 * 檢查對x,y賦值時的實際值的型別是否符合要求。
    		 * 並且在獲取它們的值時,編譯器會自動新增造型程式碼
    		 */
    		Type<Integer> t = new Type<Integer>(1,2);
    		//編譯器會檢查實參是否滿足泛型所指定型別的要求
    		t.setX(2);
    		//獲取時,無需造型(編譯器會自動補全)
    		int x = t.getX();
    		System.out.println("x:"+x);
    		System.out.println(t);
    		
    		Type<Double> t2 = new Type<Double>(1.1,2.2);
    		t2.setX(2.2);
    		double x2 = t2.getX();
    		System.out.println("x2:"+x2);
    		System.out.println(t2);
    		
    		Type<String> t3 = new Type<String>("一","二");
    		t3.setX("三");
    		String x3 = t3.getX();
    		System.out.println("x3:"+x3);
    		System.out.println(t3);
    	}
    }
    
    //泛型是編譯器認可,非虛擬機器認可。
    public class TypeDemo3 {
    	public static void main(String[] args) {
    		Type<Integer> t1 = new Type<Integer>(1,2);
    		//編譯器會檢查實參型別是否符合泛型要求
    		t1.setX(3);
    		//編譯器會自動補充造型回Integer的程式碼
    		int x1 = t1.getX();
    		System.out.println("x1:"+x1);
    		System.out.println("t1:"+t1);		
    		//當不指定泛型時,編譯器預設認為是原型Object
    		Type t2 = t1;
    		System.out.println("t2:"+t2);		
    		t2.setX("一");
    		System.out.println("t2:"+t2);		
    		//類造型異常!
    		x1 = t1.getX();
    		System.out.println("x1:"+x1);
    		System.out.println("t1:"+t1);
    		
    	}
    }